Faraday: Die URI-Validierung schlägt fehl, wenn sie reservierte Zeichen enthält

Erstellt am 4. Dez. 2020  ·  3Kommentare  ·  Quelle: lostisland/faraday

Basisinformation

  • Faraday-Version: 1.1.0
  • Ruby-Version: 2.7.1

Fehlerbeschreibung

Einer der Dienstanbieter, die ich verwende, hat URLs wie diese: https://service.com/service:search . So richten wir Faraday ein:

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

und wenn ich es aufrufe

data = Provider::Client.post(
  "service:search?limit=#{LIMIT}&offset=#{offset}", search_params
)

aber wenn ich dies mit der fraglichen URL mache, erhalte ich Folgendes:

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='

Ich gehe davon aus, dass es etwas mit dem Net/HTTP-Adapter zu tun hat, da es der Standardadapter ist, also habe ich den gleichen Aufruf manuell durchgeführt

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

und das funktioniert tatsächlich, also vermute ich, dass etwas in Faraday diese URL auf eine andere Weise als net/http validiert

bug good first issue

Hilfreichster Kommentar

@luizkowalski perfekt, ja genau das meinte ich mit

Dies funktioniert jedoch nicht in allen Fällen, da Sie möglicherweise einen relativen Pfad an die Basis anhängen müssen, der nicht mit / beginnen kann.

Faraday geht davon aus, dass die angegebene URL absolut ist, wenn sie mit / beginnt und den Pfad zur Basis entfernt hat.
Schön, dass Sie den Workaround bereits gefunden haben, aber dieser sollte noch richtig behoben sein, damit kein Workaround mehr erforderlich ist

Alle 3 Kommentare

Hallo @luizkowalski , die Ausnahme kommt von URI und wird in den ersten Zeilen der Methode query= ausgelöst:

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 zaubert interne Magie auf die Anfrage-URL, indem es sie aufteilt und neu kombiniert, um bei einigen gängigen Transformationen zu helfen, und ich vermute, dass dies zu einem bestimmten Zeitpunkt dazu führen kann, dass @opaque dank des Vorhandenseins von : in der URL.
Ich habe das Problem bis zu dieser Zeile verfolgt: https://github.com/lostisland/faraday/blob/c26df87b8653db4f270e3bcdc7a15bcdd2dd5cae/lib/faraday/connection.rb#L525
In Ihrem Beispielcode wäre base #<URI::HTTPS https://service.com/> und url wäre service:search?limit=50&offset=400 .
Interessanterweise scheint das Ergebnis ziemlich unerwartet zu sein, wenn der zweite Parameter der Methode + für URI ein : enthält!

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>

Aus irgendeinem Grund wird base entfernt und nur die URL bleibt übrig.
Die Lösung ist in diesem Fall recht einfach, es reicht aus, der URL ein / voranzustellen und die Dinge funktionieren wie erwartet:

data = Provider::Client.post(
  "/service:search?limit=#{LIMIT}&offset=#{offset}", search_params
)

Dies funktioniert jedoch nicht in allen Fällen, da Sie möglicherweise einen relativen Pfad an base anhängen müssen, der nicht mit / beginnen darf.
Bitte versuchen Sie es, indem Sie / voranstellen und lassen Sie mich wissen, ob das funktioniert, aber ich lasse dieses Problem offen, um einen Blick darauf zu werfen und eine Möglichkeit zu finden, diese Codezeile in Faraday zu reparieren, damit es funktioniert in diesem Fall.
Wenn Sie es selbst ausprobieren möchten, bewerte ich gerne eine PR 😃

@iMacTia es hat jetzt funktioniert. Die Basis-URL lautet: https://service.com/api . Als ich / zu service:search hinzufügte, bekam ich einen Fehler und bemerkte, dass das /api von der Basis-URL verschwunden war, also habe ich /api/service:search hinzugefügt und jetzt ist es in Ordnung

@luizkowalski perfekt, ja genau das meinte ich mit

Dies funktioniert jedoch nicht in allen Fällen, da Sie möglicherweise einen relativen Pfad an die Basis anhängen müssen, der nicht mit / beginnen kann.

Faraday geht davon aus, dass die angegebene URL absolut ist, wenn sie mit / beginnt und den Pfad zur Basis entfernt hat.
Schön, dass Sie den Workaround bereits gefunden haben, aber dieser sollte noch richtig behoben sein, damit kein Workaround mehr erforderlich ist

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

olleolleolle picture olleolleolle  ·  5Kommentare

JasonBarnabe picture JasonBarnabe  ·  4Kommentare

ioquatix picture ioquatix  ·  4Kommentare

jeffb-stell picture jeffb-stell  ·  5Kommentare

mokolabs picture mokolabs  ·  3Kommentare