У одного из поставщиков услуг, которого я использую, есть такие 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
и это действительно работает, поэтому я подозреваю, что что-то в Фарадея проверяет этот URL иначе, чем net / http
Привет, @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
Фарадей совершает некоторую внутреннюю магию с URL-адресом запроса, разделяя и рекомбинируя его, чтобы помочь с некоторыми общими преобразованиями, и я предполагаю, что в какой-то момент это может привести к установке @opaque
благодаря наличию :
в URL.
Я проследил проблему до этой строки: https://github.com/lostisland/faraday/blob/c26df87b8653db4f270e3bcdc7a15bcdd2dd5cae/lib/faraday/connection.rb#L525
Используя ваш пример кода, 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 теперь https://service.com/api
. Когда я добавил /
в service:search
я получил сообщение об ошибке и заметил, что /api
исчез из базового URL, поэтому я добавил /api/service:search
и теперь все в порядке.
@luizkowalski идеально, да, именно это я имел в виду
Однако это работает не во всех случаях, так как вам может потребоваться добавить относительный путь к базе, который не может начинаться с /.
Как предполагает Фарадей, предоставленный URL-адрес является абсолютным, если он начинается с /
и удаляет путь, предоставленный к базе.
Рад, что вы уже нашли обходной путь, но это все равно нужно исправить, чтобы обходной путь больше не нужен
Самый полезный комментарий
@luizkowalski идеально, да, именно это я имел в виду
Как предполагает Фарадей, предоставленный URL-адрес является абсолютным, если он начинается с
/
и удаляет путь, предоставленный к базе.Рад, что вы уже нашли обходной путь, но это все равно нужно исправить, чтобы обходной путь больше не нужен