L'un des fournisseurs de services que j'utilise a des URL comme celle-ci : https://service.com/service:search
. Voici comment nous avons configuré Faraday :
class Provider::Client
...
delegate :post, :patch, :delete, :put, to: :client
def client
Faraday.new(url: 'https://service.com/') do |faraday|
faraday.headers = headers.merge(content_type: content_type)
faraday.response(:json, content_type: CONTENT_TYPE)
faraday.basic_auth(USER, PASSWORD)
faraday.adapter(Faraday.default_adapter)
end
end
end
et quand je l'invoque
data = Provider::Client.post(
"service:search?limit=#{LIMIT}&offset=#{offset}", search_params
)
mais quand je fais cela avec l'URL en question, j'obtiens ceci :
URI::InvalidURIError: query conflicts with opaque
from /Users/luiz/.rbenv/versions/2.7.1/lib/ruby/2.7.0/uri/generic.rb:832:in `query='
Je suppose que c'était quelque chose lié à l'adaptateur net/http car c'est l'adaptateur par défaut donc j'ai fait le même appel manuellement
require "uri"
require "net/http"
url = URI("https://service.com/service:search?limit=50&offset=400")
https = Net::HTTP.new(url.host, url.port);
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Accept"] = "custom_header"
request["Authorization"] = "Basic xxx="
request["Content-Type"] = "application/json"
request.body = "long_json"
response = https.request(request)
puts response.read_body
et cela fonctionne réellement, donc je soupçonne que quelque chose dans Faraday valide cette URL d'une manière différente de net/http
Salut @luizkowalski , l'exception vient de URI
et est levée dans les premières lignes de la méthode query=
:
def query=(v)
return <strong i="9">@query</strong> = nil unless v
raise InvalidURIError, "query conflicts with opaque" if <strong i="10">@opaque</strong>
...
end
Faraday fait de la magie interne sur l'URL de demande en la divisant et en la recombinant pour aider à certaines transformations courantes, et je suppose qu'à un moment donné, cela peut entraîner la définition du @opaque
grâce à la présence du :
dans l'URL.
J'ai retracé le problème jusqu'à cette ligne : https://github.com/lostisland/faraday/blob/c26df87b8653db4f270e3bcdc7a15bcdd2dd5cae/lib/faraday/connection.rb#L525
En utilisant votre exemple de code, base
serait #<URI::HTTPS https://service.com/>
et url
serait service:search?limit=50&offset=400
.
Maintenant, assez intéressant, si le deuxième paramètre de la méthode +
pour l'URI contient un :
, il semble que le résultat soit assez inattendu !
2.7.1 > url
=> "service:search?limit=50&offset=400"
2.7.1 > base
=> #<URI::HTTPS https://service.com/>
2.7.1 > base + url
=> #<URI::Generic service:search?limit=50&offset=400>
Pour une raison quelconque, le base
est supprimé et seule l'URL est laissée.
Le correctif est assez simple dans ce cas, il suffit d'ajouter un /
à l'URL et les choses fonctionnent comme prévu :
data = Provider::Client.post(
"/service:search?limit=#{LIMIT}&offset=#{offset}", search_params
)
Cependant, cela ne fonctionne pas dans tous les cas car vous devrez peut-être ajouter un chemin relatif au base
qui ne peut pas commencer par /
.
Veuillez essayer ceci en ajoutant le /
et laissez-moi savoir si cela fonctionne, mais je laisserai ce problème ouvert pour jeter un œil et trouver un moyen possible de corriger cette ligne de code dans Faraday afin qu'elle fonctionne dans ce cas.
Si vous voulez essayer vous-même, je serais ravi de revoir un PR
@iMacTia cela a fonctionné maintenant. L'URL de base est : https://service.com/api
. Lorsque j'ai ajouté le /
à service:search
j'ai eu une erreur et j'ai remarqué que le /api
avait disparu de l'URL de base, j'ai donc ajouté /api/service:search
et maintenant tout va bien
@luizkowalski parfait, oui c'est exactement ce que je voulais dire avec
Cependant, cela ne fonctionne pas dans tous les cas car vous devrez peut-être ajouter un chemin relatif à la base qui ne peut pas commencer par /.
Comme faraday suppose que l'URL fournie est absolue si elle commence par /
et a supprimé le chemin fourni à la base.
Heureux que vous ayez déjà trouvé la solution de contournement, mais cela devrait toujours être corrigé correctement afin que la solution de contournement ne soit plus nécessaire
Commentaire le plus utile
@luizkowalski parfait, oui c'est exactement ce que je voulais dire avec
Comme faraday suppose que l'URL fournie est absolue si elle commence par
/
et a supprimé le chemin fourni à la base.Heureux que vous ayez déjà trouvé la solution de contournement, mais cela devrait toujours être corrigé correctement afin que la solution de contournement ne soit plus nécessaire