Faraday: URI 验证在包含保留字符时失败

创建于 2020-12-04  ·  3评论  ·  资料来源: lostisland/faraday

基础信息

  • 法拉第版本:1.1.0
  • 红宝石版本:2.7.1

问题描述

我使用的服务提供商之一有这样的 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

bug good first issue

最有用的评论

@luizkowalski完美,是的,这正是我的意思

然而,这并不适用于所有情况,因为您可能需要将相对路径附加到不能以 / 开头的基数。

由于 faraday 假设提供的 URL 是绝对的,如果它以/开头并删除了提供给 base 的路径。
很高兴您已经找到了解决方法,但这仍应正确修复,以便不再需要解决方法

所有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 来对请求 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 的路径。
很高兴您已经找到了解决方法,但这仍应正确修复,以便不再需要解决方法

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

ryanbyon picture ryanbyon  ·  3评论

yusefu picture yusefu  ·  3评论

jeffb-stell picture jeffb-stell  ·  5评论

mokolabs picture mokolabs  ·  3评论

aleksb86 picture aleksb86  ·  3评论