我使用的服务提供商之一有这样的 URL: https://service.com/service:search
。 这是我们设置法拉第的方式:
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
嗨@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 来对请求 url 进行一些内部魔术以帮助进行一些常见的转换,我认为在某些时候它可能会导致@opaque
被设置,这要归功于:
网址中的
我已经将问题追溯到这一行: https :
使用您的示例代码, base
将是#<URI::HTTPS https://service.com/>
, url
将是service:search?limit=50&offset=400
。
现在,有趣的是,如果 URI 的+
方法的第二个参数包含:
,结果似乎很出乎意料!
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 是绝对的,如果它以/
开头并删除了提供给 base 的路径。
很高兴您已经找到了解决方法,但这仍应正确修复,以便不再需要解决方法
最有用的评论
@luizkowalski完美,是的,这正是我的意思
由于 faraday 假设提供的 URL 是绝对的,如果它以
/
开头并删除了提供给 base 的路径。很高兴您已经找到了解决方法,但这仍应正确修复,以便不再需要解决方法