_NB: Bitte lassen Sie mich wissen, ob dies stattdessen in faraday_middleware
. Da es sich um zwei Middlewares handelt, wusste ich nicht, wo ich es hinstellen sollte._
Beim Herstellen einer Verbindung erwarte ich (wie dokumentiert), dass die Middleware in der Reihenfolge ausgeführt wird, in der sie deklariert wurde. Wenn jedoch eine Anforderung fehlschlägt und ich lade :json
Parsen Middleware durch die gefolgt :retry
Middleware, env.body
unparsed im Rahmen des ist :retry
Middle :retry_if
Block:
Ich muss den :retry_if
Block für die JSON
-dekodierte Nachricht ausführen, da das JSON-Dokument sehr groß sein kann, wenn die Anforderung erfolgreich ist, und die Alternative besteht darin, es ein zweites Mal in retry_if
zu parsen
<strong i="23">@_client</strong> ||= Faraday.new(url: ROOT_URL) do |f|
f.options[:timeout] = 10
f.headers['Content-Type'] = 'application/json'
f.use :instrumentation, name: INSTRUMENTATION_EVENT_NAME
f.response :json, content_type: /\bjson$/
f.request :retry, FARADAY_RETRY_OPTIONS
end
Hinweis: Wenn ich f.instance_variable_get :@handlers
drucke, sehe ich innerhalb des Blocks die Middleware in der Reihenfolge, in der ich sie deklariert habe.
Wenn eine Anfrage fehlschlägt und ich diese Ausdrücke im :retry_if
Block der :retry
Middleware auswerte, erhalte ich die folgende Ausgabe:
(byebug) environment.response.to_hash.without(:url)
{:status=>405, :body=>"{\"message\": \"The method is not allowed for the requested URL.\"}\n", :response_headers=>{"date"=>"Fri, 23 Apr 2021 18:17:16 GMT", "content-type"=>"application/json", "content-length"=>"64", "connection"=>"keep-alive", "server"=>"gunicorn", "allow"=>"HEAD, OPTIONS, GET"}}
(byebug) environment.response.body
"{\"message\": \"The method is not allowed for the requested URL.\"}\n"
(byebug) environment.response.body.class
String
Im Grunde weigert sich die Parser-Middleware einfach, zuerst ausgeführt zu werden.
Der JSON ist wohlgeformt und der Content-Type
Header der Antwort ist korrekt gesetzt, also bin ich ratlos.
Meine einzige Vermutung ist, dass es etwas mit #response
Middleware zu tun hat, die immer vor der #request
Middleware ausgeführt wird, aber in diesem Fall ist retry
#request
Middleware eine falsche Bezeichnung da es implizit ausgewertet werden muss, nachdem die Antwort zurückgegeben wurde.
Update: Ich habe die Reihenfolge der beiden Middlewares im Verbindungskonfigurationsblock buchstäblich umgedreht (während ich dachte "das kann unmöglich funktionieren") und jetzt funktioniert es perfekt. Ich lasse dies jedoch, weil ich keine Ahnung habe, was los ist und es immer noch wie ein Fehler aussieht (oder zumindest besser dokumentiert werden sollte).
Hallo @mvastola , was du erlebst, ist das erwartete Verhalten!
Ich weiß, es ist anfangs schwer, sich damit zurechtzufinden, aber da der Middleware-Stapel dem eines Rack-Stacks ähnelt, werden Middleware in umgekehrter Reihenfolge für Antworten durchsucht.
Auf unserer Website haben wir ein Bild, das dies veranschaulicht, um es leichter zu verstehen.
Du hast also schon das Richtige getan 🙌! Indem Sie die Middleware :json
nach der Middleware :retry
, erlauben Sie, dass die Antwort zuerst von dieser verarbeitet wird, und die Middleware :retry
findet den Antworttext geparst.
Ich schließe das jetzt, aber melde dich gerne, wenn du weitere Fragen hast
Danke für die schnelle, freundliche und ausführliche Erklärung. Es ist nicht so schwer zu verstehen, aber hier ist es ein bisschen unintuitiv. Ich frage mich, ob es einen effektiven Weg gibt, es weniger zu machen.
Ich hatte die von Ihnen verlinkte Dokumentation tatsächlich gesehen und dachte, ich wüsste, was ich tun musste. (Ich habe das Bild und das Zeug zur "innersten" Middleware gesehen, aber ich habe nicht wirklich verstanden, dass dies eine Umkehrung der Reihenfolge bedeutet.)
Das gezeigte Bild ist in Bezug auf die Interna der Middleware informativ, es kann jedoch hilfreich sein, es mit einem visuellen Hinweis darauf zu ergänzen, wie sich die Reihenfolge im Konfigurationsblock auf die Ausführungsreihenfolge auswirkt.
Darüber hinaus gibt es eine Reihe von Details dieser Implementierung, die dies unintuitiv machen:
Es gibt drei verschiedene Funktionen in faraday
, um Middleware hinzuzufügen, und sie sind nicht austauschbar: Jede Middleware scheint nur mit einer von ihnen zu funktionieren. Dies erweckt den Anschein, als ob es drei verschiedene Middleware-Stacks (oder Anordnungen) unabhängig voneinander gäbe.
Was diese drei verschiedenen Namen/Gruppen von Middleware tun, ist sehr unklar, da jedoch die meisten Middleware _nicht_ an beiden Enden des Request->Response-Pfads ausgeführt wird, würde ein Benutzer wahrscheinlich annehmen, dass "Anfrage"-Aufgaben immer vor "Antwort" stattfinden. verwandte Dinge.
Das Rack-Schlüsselwort zum Hinzufügen von Middleware, use
, gilt in Faraday (soweit ich das beurteilen kann) nur für diese Art von Middleware – Middleware, die sowohl die Anfrage als auch die Antwort umschließt.
Wie auch immer, ich freue mich, zu versuchen, einige Ideen zu entwickeln, wenn Sie offen dafür sind, die API für dieses Problem zu optimieren. Sonst verstehe ich das jetzt wenigstens. Ich sage dies nur, weil ich leicht sehen kann, dass andere Benutzer hier die gleiche Verwirrung erleiden.
Danke @mvastola , das ist ein unschätzbares Feedback 🙏!
Und um fair zu sein, dies ist nicht das erste Mal, dass ich von diesen Dingen höre.
Was die Dokumentation angeht, bin ich mir einig, dass wir noch weit davon entfernt sind, daher ist jeder Beitrag zur Verbesserung sehr willkommen (es gibt tatsächlich einen sehr aktuellen Diskussionsthread dazu !).
Die Punkte zur Konfiguration sind auch sehr gültig, lassen Sie mich nur sagen, dass die Verwirrung der Methoden request
, response
und use
mehrmals aufgeworfen wurde, bis zu dem Punkt, dass ich tatsächlich erwägen, sie einfach zugunsten von use
und es dann der Middleware zu überlassen, zu dokumentieren, was/wann sie die Anfrage/Antwort manipuliert.
Ich würde also vorschlagen, noch keine PR zu drängen, um diese API zu ändern, aber wir sind sehr offen dafür, die Community über Diskussionen zu diesem Thema zu hören
Hilfreichster Kommentar
Hallo @mvastola , was du erlebst, ist das erwartete Verhalten!
Ich weiß, es ist anfangs schwer, sich damit zurechtzufinden, aber da der Middleware-Stapel dem eines Rack-Stacks ähnelt, werden Middleware in umgekehrter Reihenfolge für Antworten durchsucht.
Auf unserer Website haben wir ein Bild, das dies veranschaulicht, um es leichter zu verstehen.
Du hast also schon das Richtige getan 🙌! Indem Sie die Middleware
:json
nach der Middleware:retry
, erlauben Sie, dass die Antwort zuerst von dieser verarbeitet wird, und die Middleware:retry
findet den Antworttext geparst.Ich schließe das jetzt, aber melde dich gerne, wenn du weitere Fragen hast