أحد مزودي الخدمة الذين أستخدمهم لديه عناوين 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
وهذا يعمل بالفعل ، لذا أظن أن شيئًا ما في Faraday يتحقق من صحة عنوان 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
يقوم Faraday ببعض السحر الداخلي على عنوان 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
والذي لا يمكن أن يبدأ بـ /
.
يُرجى تجربة هذه المحاولة عن طريق إضافة /
وإخباري إذا كان ذلك ناجحًا ، لكنني سأترك هذه المشكلة مفتوحة لإلقاء نظرة وإيجاد طريقة ممكنة لإصلاح هذا السطر من التعليمات البرمجية في Faraday بحيث يعمل في هذه الحالة.
إذا كنت تريد أن تجربها بنفسك ، فسيسعدني مراجعة العلاقات العامة 😃
iMacTia عملت الآن. عنوان URL الأساسي هو: https://service.com/api
. عندما أضفت /
إلى service:search
حصلت على خطأ ولاحظت أن /api
قد اختفى من عنوان URL الأساسي لذلك أضفت /api/service:search
والآن أصبح الأمر جيدًا
luizkowalski مثالي ، نعم هذا بالضبط ما قصدته
ومع ذلك ، لا يعمل هذا في جميع الحالات حيث قد تحتاج إلى إلحاق مسار نسبي بالقاعدة والذي لا يمكن أن يبدأ بـ /.
كما يفترض faraday أن عنوان URL المقدم مطلق إذا بدأ بـ /
وأزال المسار المقدم إلى القاعدة.
يسعدني أنك عثرت بالفعل على الحل البديل ، ولكن لا يزال يتعين إصلاح ذلك بشكل صحيح حتى لا يكون الحل البديل ضروريًا بعد الآن
التعليق الأكثر فائدة
luizkowalski مثالي ، نعم هذا بالضبط ما قصدته
كما يفترض faraday أن عنوان URL المقدم مطلق إذا بدأ بـ
/
وأزال المسار المقدم إلى القاعدة.يسعدني أنك عثرت بالفعل على الحل البديل ، ولكن لا يزال يتعين إصلاح ذلك بشكل صحيح حتى لا يكون الحل البديل ضروريًا بعد الآن