Faraday: 予約文字が含まれている場合、URI検証は失敗します

作成日 2020年12月04日  ·  3コメント  ·  ソース: lostisland/faraday

基本情報

  • ファラデーバージョン:1.1.0
  • Rubyバージョン:2.7.1

問題の説明

私が使用しているサービスプロバイダーの1つには、 https://service.com/service:searchようなURLがあります。 これがファラデーの設定方法です。

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

そして私がそれを呼び出すとき

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

しかし、問題のURLでこれを行うと、次のようになります。

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

これはデフォルトのアダプターであるため、net / httpアダプターに関連するものだと思います。そのため、同じ呼び出しを手動で行いました。

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

これは実際に機能するので、ファラデーの何かがnet / httpとは異なる方法でこのURLを検証しているのではないかと思います。

bug good first issue

最も参考になるコメント

@luizkowalski完璧です、はい、それはまさに私が意味したことです

ただし、/で開始できないベースに相対パスを追加する必要がある場合があるため、これはすべての場合に機能するとは限りません。

faradayは、提供されたURLが/で始まり、ベースに提供されたパスを削除した場合、絶対的なものと見なします。
すでに回避策を見つけてよかったですが、回避策が不要になるように、これは適切に修正する必要があります。

全てのコメント3件

こんにちは@luizkowalski 、例外はURIから来ており、 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は、リクエストURLを分割して再結合することで内部的な魔法をかけ、いくつかの一般的な変換を支援します。ある時点で、 :存在により、 @opaqueが設定される可能性があると思います。 URLの:
私はこの行まで問題を追跡しました: https
サンプルコードを使用すると、 base#<URI::HTTPS https://service.com/>なり、 urlservice:search?limit=50&offset=400ます。
興味深いことに、URIの+メソッドの2番目のパラメーターに:が含まれている場合、結果はまったく予想外のようです。

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>

何らかの理由で、 baseが削除され、URLのみが残ります。
この場合、修正は非常に簡単です。URLの前に/を追加するだけで十分であり、期待どおりに機能します。

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

ただし、 /開始できないbase相対パスを追加する必要がある場合があるため、これはすべての場合に機能するとは限りません。
/を前に付けて試してみて、それが機能するかどうかを知らせてください。ただし、この問題を開いたままにして、ファラデーでそのコード行を修正して修正できる方法を見つけます。この場合は機能します。
自分で試してみたい場合は、PRを喜んでレビューします😃

@iMacTiaそれは今働いた。 ベースURLはhttps://service.com/apiです。 私は追加すると/するservice:search私はエラーを持っていることに気づい/api 、私は追加して、ベースURLから消えていた/api/service:searchと今の罰金

@luizkowalski完璧です、はい、それはまさに私が意味したことです

ただし、/で開始できないベースに相対パスを追加する必要がある場合があるため、これはすべての場合に機能するとは限りません。

faradayは、提供されたURLが/で始まり、ベースに提供されたパスを削除した場合、絶対的なものと見なします。
すでに回避策を見つけてよかったですが、回避策が不要になるように、これは適切に修正する必要があります。

このページは役に立ちましたか?
0 / 5 - 0 評価