Faraday: Définit automatiquement @handler sur Faraday.default_adapter si non spécifié.

Créé le 22 févr. 2012  ·  35Commentaires  ·  Source: lostisland/faraday

Normalement, pour nos scripts simples, nous définissons Faraday.default_adapter une fois en haut, mais tout en travaillant avec Github qui (sans vouloir vous offenser) aime les redirections, nous devons utiliser faraday_middleware (enfin, pas besoin d'utiliser) pour suivre les redirections, ce qui nous oblige à faire un bloc (je supposer) Je pense qu'il serait préférable que Faraday suppose que le gestionnaire doit être défini sur Faraday.default_adapater s'il n'est pas défini avec l'utilisation dans le bloc, cela permet d'économiser du codage et du code redondant IMO.

refactoring

Commentaire le plus utile

+1 à ça. À tout le moins, une erreur indiquant qu'aucun adaptateur n'a été spécifié, ou mieux, utilisez simplement le default_adapter si rien n'a été spécifié.

Tous les 35 commentaires

Je ne suis pas sûr de cela, mais je le laisserai ouvert. La pile par défaut est UrlEncoded + default_adapter. Si vous définissez votre propre pile, vous devez la définir à 100 %, y compris l'adaptateur. Mais c'est vrai que j'utilise le plus souvent le default_adapter, donc ça pourrait aussi bien être un défaut.

Je pensais à refactoriser les adaptateurs Faraday, en en faisant des points de terminaison au lieu de middleware (selon # 47). Cette fonctionnalité pourrait faire partie de ce changement.

:+1: Cela m'a mordu pour la deuxième fois cette année. Vous penseriez que j'apprendrais. Ce serait bien si c'était réparé.

Compromis : Faraday.with_default_stack() , de sorte que nous versons des âmes qui essaient d'utiliser Faraday pour la première fois sans avoir à connaître "la pile par défaut" juste pour pouvoir suivre les redirections. Raisonnable?

@jbrains Oui, je me rends compte que ce n'est pas convivial. Nous pourrions faire en sorte qu'une erreur descriptive soit générée si vous n'avez pas monté d'adaptateur, ou si vous l'avez monté au mauvais endroit.

J'ai fait ça dans mon projet :

        def faraday_with_default_adapter(base, &block)
          Faraday.new(base) { | connection |
            yield connection
            connection.adapter Faraday.default_adapter
          }
        end

Je sais que vous ne voulez pas prendre en charge toutes les permutations, mais il semble que presque tout le monde finira par le faire. :) Si je savais comment ajouter le bit UrlEncoded (je ne l'ai pas encore rencontré), alors je l'ajouterais ici.

Une vérification de style lint avec une erreur descriptive serait certainement utile. Merci. Même ainsi, un petit pokayoke nous aiderait encore plus.

Je vais envisager de vous envoyer une pull request à l'avenir. En attendant, merci.

Cela a consommé quelques heures de travail lorsque j'ai essayé de faire un téléchargement et que je n'ai pas spécifié l'adaptateur par défaut (que je supposais déjà défini, car c'est celui par défaut). J'ai continué à déboguer et à inspecter les objets de réponse/demande et il n'y avait aucun problème, sauf qu'il me manquait la redoutable ligne d'adaptateur par défaut.

Je pense que cela devrait au moins être documenté sur le README quelque part ou au moins m'avertir que j'avais besoin d'un adaptateur explicite.

Merci!

Cela m'a mordu aujourd'hui aussi avec l'exemple suivant:

conn = Faraday.new(url: "http://www.example.com") do |faraday|
  faraday.response :json, content_type: /\bjson$/
end

response = conn.get("stuff")

L'erreur est apparue dans faraday_middleware lorsqu'il a essayé d'obtenir les en-têtes de réponse alors qu'ils étaient nil . Un peu trompeur. Une décision a-t-elle été prise concernant la "meilleure façon" de gérer cela ?

  • Utilisez l'adaptateur par défaut s'il n'est pas spécifié (le meilleur IMO)
  • Génère une erreur si aucune n'est spécifiée
  • Mettre à jour le README

Je serais plus qu'heureux de soumettre un PR

Pas besoin de RP. Nous essaierons de résoudre ce problème dans la prochaine version.

Merci, @mislav.

Ouais, j'ai perdu une heure hier à courir après celui-ci. Ravi de voir qu'un correctif est en route. Quand la prochaine version est-elle susceptible d'atterrir? Le dernier était en janvier, ce qui semble très long.

Le jeudi 2 octobre 2014 à 17h49, John Carney [email protected]
a écrit:

Quand la prochaine version est-elle susceptible d'atterrir? Le dernier était en janvier, ce qui semble
un temps terriblement long.

Étant donné que 0.8 et 0.9 devraient être gelés, le correctif pour cela est susceptible de
n'arrivent qu'en 1.0, dont je ne sais pas quand ce sera.

Qu'en est-il de ceci pour un simple terrain d'entente : si une tentative est faite pour faire une demande alors qu'il n'y a pas d'adaptateur, une exception est levée.

Ou existe-t-il un cas d'utilisation pour "faire des demandes" sans adaptateur ?

Le vendredi 3 octobre 2014 à 14 h 07, John Bachir [email protected]
a écrit:

Qu'en est-il de ceci pour un simple terrain d'entente : si une tentative est faite pour faire
une demande lorsqu'il n'y a pas d'adaptateur, une exception est levée.

Comment détectons-nous si un adaptateur est monté ?

Notez qu'un adaptateur personnalisé implémenté par quelqu'un n'a pas nécessairement
à la sous-classe Faraday::Adapter.

Ah, je vois. Étant donné que l'adaptateur est un frère de l'autre middleware et que la seule API à tester est l'API de rack standard, il n'y a aucun moyen d'identifier si un middleware est un adaptateur http. :trombone triste:

Si cela est implémenté, les changements dans #496 peuvent probablement être annulés (s'ils ont été fusionnés en premier lieu).

+1 à ça. À tout le moins, une erreur indiquant qu'aucun adaptateur n'a été spécifié, ou mieux, utilisez simplement le default_adapter si rien n'a été spécifié.

Le nom prête à confusion, lorsque vous devez ajouter des middlewares, vous vous attendez à ajouter des middlewares et à conserver le default_adapter en place.

C'est idiot que nous nous retrouvions sans adaptateur du tout. Tu ne veux jamais ça...

Je veux simplement assurer à tout le monde que nous discutons en interne d'une stratégie pour gérer cela.
Je sais que cela semble être une vérification facile, mais comme @mislav l'a déjà expliqué, nous avons actuellement un problème lié à la liberté dont disposent les utilisateurs pour ajouter des adaptateurs dans la pile de middlewares.
En fait, à l'heure actuelle, un "adaptateur" n'est rien d'autre qu'un middleware, comme un autre, exécutant la requête.
Désormais, lorsque vous définissez votre propre pile de middlewares, nous perdons la capacité de détecter l'adaptateur à partir des autres middlewares, à moins que vous n'utilisiez la méthode #adapter lors de la création de la connexion. Malheureusement, son utilisation n'est pas obligatoire pour le moment, ce qui rend impossible la détection de l'adaptateur.

Cool! Merci pour le headsup ici :)

Le 14 novembre 2016, à 14h45, Mattia [email protected] a écrit :

Je veux juste assurer à tout le monde que nous discutons en interne d'une stratégie
pour gérer cela.
Je sais que cela ressemble à une vérification facile, mais comme
@mislav a déjà expliqué que nous avons un problème au
moment lié à la liberté que les gens ont d'ajouter des adaptateurs dans le
pile de middlewares.
En fait, pour le moment, "adapter" n'est rien d'autre qu'un middleware, comme
tout autre, exécutant la demande.
Désormais, lorsque vous définissez votre propre pile de middlewares, nous perdons la possibilité de
détecter l'adaptateur des autres middlewares, sauf si vous utilisez le #adapter
méthode lors de la création de la connexion. Malheureusement, son utilisation n'est pas
obligatoire pour le moment, rendant la détection de l'adaptateur impossible.


Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub ou désactivez lefil .

https://v2.developer.pagerduty.com/docs/authentication

Ainsi, la documentation de l'API PagerDuty, pour ruby+faraday, présente ce comportement ; si vous utilisez simplement leur code, cela ne fonctionne pas. (À moins qu'ils ne le réparent, ce qu'ils feront probablement maintenant que j'ai signalé l'absence d'adaptateur.)

Honnêtement, ma suggestion serait:

Si j'appelle "conn.get" et que conn n'a pas d'adaptateur, déclenchez une exception me disant que . Le comportement actuel est de revenir immédiatement mais de ne pas avoir mis les choses dans les états que Faraday décrit comme résultant de l'appel de get. Ainsi, par exemple, ".status" est toujours nul. C'est vraiment un comportement surprenant ! Je dirais que "je ne peux rien faire parce que je n'ai aucune idée de ce que vous voulez que je fasse" devrait probablement produire une sorte de diagnostic.

Salut @seebs, je sais que cela semble idiot, mais j'ai expliqué pourquoi ce n'est pas aussi facile à faire que cela puisse paraître dans mon commentaire précédent :

Lorsque vous définissez votre propre pile de middlewares, nous perdons la capacité de détecter l'adaptateur à partir des autres middlewares, à moins que vous n'utilisiez la méthode #adapter lors de la construction de la connexion. Malheureusement, son utilisation n'est pas obligatoire pour le moment, ce qui rend impossible la détection de l'adaptateur.

J'ai essayé de retracer ce qui se passe, et il me manque quelque chose.

Si vous faites la chose évidente que tant de gens font et que vous ne spécifiez pas l'adaptateur, lorsque vous appelez get, vous finissez par vous retrouver dans le build_response de rack_builder, qui fait app.call. Et je ne sais pas vraiment où cela va, car je ne vois pas où l'application a été définie.

Donc, je suppose que ce que je me demande, c'est que si vous ne faites jamais "adapter : foo", qu'est-ce qui finit par recevoir l'appel ?

Une solution triviale :
def initialiser(gestionnaires = [])
@handlers = gestionnaires
si block_given ?

  • self.adapter Faraday.default_adapter
    construire(&Proc.nouveau)
    elsif @handlers.empty ?

... Je pense que cela fonctionnerait (-ish) ?

Alternativement, après build(&Proc.new), vérifiez si self.adapter a été défini.

Même si adapter :foo est le moyen le plus utilisé pour configurer l'adaptateur, il existe d'autres moyens de le faire.
#adapter n'est en fait qu'une aide, mais vous pouvez utiliser #use pour mettre un adaptateur dans la pile :

conn = Faraday.new(url: "http://www.example.com") do |faraday|
  faraday.response :logger
  faraday.use Faraday::Adapter::NetHttp
end

Alors, qu'est-ce qu'un adaptateur pour le moment ? Rien de plus qu'un middleware qui effectue l'appel et stocke le résultat dans env . C'est pourquoi nous ne pouvons pas simplement compter sur l'appel de la méthode #adapter . Nous ne pouvons pas compter sur le middleware qui fonctionne comme un adaptateur pour hériter de Faraday::Adapter car ce n'est pas non plus une exigence.

La seule solution est d'utiliser la version Faraday 1.0 pour rendre obligatoire l'utilisation de la méthode #adapter , ou de supposer qu'elle sera utilisée et de pousser l'adaptateur par défaut dans la pile si la méthode n'est pas appelée.

Nous discutons toujours en interne de celle qui serait la meilleure solution, car d'une manière ou d'une autre, nous finirons par avoir des gens qui obtiendront des résultats inattendus après la mise à jour.
C'est ce qui arrive à beaucoup de gens la première fois qu'ils utilisent Faraday, je suis d'accord, mais c'est certainement pire quand cela se produit sur votre système de production après avoir exécuté bundle update :)

Je pense que ce que je ne comprends pas, c'est... Si vous ne configurez jamais d'adaptateur, qu'est-ce qui finit par gérer l'appel et stocker le résultat ? Il y a une invocation qui, si vous avez choisi un adaptateur, utilise la méthode call() de l'adaptateur, je pense. Si vous n'avez pas choisi d'adaptateur, quel code est réellement exécuté ?

C'est là que j'ai choisi l'adaptateur, sans utiliser la méthode #adapter .

  faraday.use Faraday::Adapter::NetHttp

Prenez mon extrait de mon commentaire précédent et essayez-le, cela fonctionnera.
Le fait est que vous pouvez pousser un adaptateur dans la pile de plusieurs façons, et une fois qu'il est là, il sera utilisé dans la requête (en appelant la méthode #call )

Désolé, je n'ai apparemment pas été clair. Je suis conscient que vous pouvez choisir un adaptateur de plusieurs façons.

Mais considérez l'erreur courante des débutants de ne pas choisir d'adaptateur, puis d'appeler conn.get(...). Que se passe-t-il réellement, à part "rien qui n'ait d'effet" ?

J'ai essayé de retracer les appels et je n'ai pas pu comprendre ce qui se passait réellement. Il semble que Connection ait défini un get par défaut qui appelle run_request. Cela appelle à son tour build_request et build_response, et je pense que cela se termine dans build_response() de rack_builder, qui appelle app.call(), et il semble que l'application génère un objet Response qui gère l'appel(). Mais ensuite je deviens confus. Je ne vois même pas Response définir une méthode call(), et je n'arrive pas à comprendre ce qui finit par faire appeler la méthode call().

Je suppose en quelque sorte qu'il y a quelque chose qui a une méthode d'appel, qui est invoquée. Si vous avez sélectionné un adaptateur, vous obtenez la méthode d'appel de cet adaptateur. Si vous n'avez pas sélectionné d'adaptateur, d'où vient la méthode d'appel qui s'exécute réellement ?

Après avoir configuré la requête et la réponse, Connection parcourt chaque middleware et appelle la méthode call(env) dessus, dans le même ordre que la pile est remplie.
Il ne fait aucune distinction entre les "middlewares normaux" et l'adaptateur, il suppose simplement que l'un des middlewares EST l'adaptateur. S'il n'y a pas de "middleware d'adaptateur" dans la pile, tous les autres middlewares seront appelés (méthode call ), mais aucun d'entre eux n'exécutera efficacement la requête (c'est le rôle de l'adaptateur).
Ce qui signifie que la réponse manquera d'état, de corps et de tous les autres champs remplis par le "middleware de l'adaptateur".

Je comprends que ce n'est pas très facile, mais j'espère que c'est plus clair maintenant 😅

Ah-hah ! C'est ce que je n'avais pas compris. Il ne m'est pas venu à l'esprit qu'ils fourniraient tous des fonctions call().

Que se passe-t-il si, après avoir tout appelé, le code déclenche une exception si le statut n'est pas défini ? "StatusNotSetException : le statut n'a pas été défini. Il est fort probable que votre middleware ne spécifie pas d'adaptateur pour effectuer réellement la récupération du réseau."

J'aimerais vraiment que cela soit corrigé !

Corrigé dans #750 @iMacTia - voudriez-vous fermer ceci ?

@olleolleolle ouais bon point ! Je pensais que cela allait se fermer automatiquement en le mentionnant :(

Il semble que celui-ci n'ait jamais été publié ? Y a-t-il une chance de voir une version mineure avant la 1.0 ? :speak_no_evil:

@franzliedke vous avez raison, ceci est actuellement inclus dans la v1.0 et je suis d'accord qu'il a été fusionné il y a un certain temps 😅.
Nous avons cependant fait beaucoup de progrès vers la version 1.0 et je dirais que nous sommes assez proches de la franchir.
Essayez de nous donner un peu plus de temps, ça vaudra la peine d'attendre 😃

Ravi de l'entendre!

Désolé d'être un peu exigeant - je sais à quel point l'open source peut être stressant. Merci pour l'excellent logiciel !

Pas du tout @franzliedke !
Appréciez le coup de pouce, nous devrions vraiment viser et publier la v1.0 le plus tôt possible.
Regardez le repo si vous ne le faites pas déjà pour ne pas manquer le lancement 👍

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

aleksb86 picture aleksb86  ·  3Commentaires

t3hk0d3 picture t3hk0d3  ·  3Commentaires

jedeleh picture jedeleh  ·  3Commentaires

jordansissel picture jordansissel  ·  5Commentaires

Lewiscowles1986 picture Lewiscowles1986  ·  4Commentaires