Faraday: Rety Middleware wird nach dem Parser nicht ausgeführt

Erstellt am 23. Apr. 2021  ·  4Kommentare  ·  Quelle: lostisland/faraday

Basisinformation

  • Faraday-Version: 1.4.1
  • Ruby-Version: 2.7.2

Fehlerbeschreibung

_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

Schritte zum Reproduzieren

<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.

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

Alle 4 Kommentare

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.

Dokumente

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.

Aufbau

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

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen