问题
I'm using Faraday to create an SDK that will interact with an API, and I need to send two headers API_SIGNATURE and API_REQUEST_TIME, so that's what I've created:
class APIClient
def initialize(api_key)
@api_key = api_key
end
def get_users
request.post('/users')
end
private
def request
Faraday.new(@@BASE_API_URL, headers: headers)
end
def headers
timestamp = Time.now.to_i.to_s
return {
'API_SIGNATURE': Digest::MD5.hexdigest(@api_key + timestamp),
'API_REQUEST_TIME': timestamp
}
end
end
And for some reason Faraday is changing API_SIGNATURE
to Api-Signature
and API_REQUEST_TIME
to Api-Request-Time
.
I would like to prevent that from happening. Someone suggested to use patron:
def request
Faraday.new(@@BASE_API_URL, headers: headers) do |faraday|
faraday.adapter :patron
end
end
But that doesn't work. The following error is raised:
/Users/me/.rvm/gems/ruby-2.4.9/gems/patron-0.13.3/lib/patron/session.rb:330:in `handle_request': Operation timed out after 1004 milliseconds with 0 out of 0 bytes received (Faraday::TimeoutError)
from /Users/me/.rvm/gems/ruby-2.4.9/gems/patron-0.13.3/lib/patron/session.rb:330:in `request'
from /Users/me/.rvm/gems/ruby-2.4.9/gems/faraday-0.17.0/lib/faraday/adapter/patron.rb:29:in `call'
from /Users/me/.rvm/gems/ruby-2.4.9/gems/faraday-0.17.0/lib/faraday/rack_builder.rb:143:in `build_response'
from /Users/me/.rvm/gems/ruby-2.4.9/gems/faraday-0.17.0/lib/faraday/connection.rb:387:in `run_request'
from /Users/me/.rvm/gems/ruby-2.4.9/gems/faraday-0.17.0/lib/faraday/connection.rb:175:in `post'
from api.rb:32:in `analyze_text'
from api.rb:38:in `full_analysis'
from api.rb:65:in `<main>'
Thank you.
======= Update ==========
The problem reduced:
headers = { API_SIGNATURE: '', API_REQUEST_TIME: '' }
conn = Faraday.new('https://api.test.io', headers: headers) do |f|
f.adapter :patron
end
puts conn.headers
回答1:
This error occurs because Faraday uses Net::HTTP by default and Net::HTTP changes the case of your header keys. You can read more about this issue at this related question.
You can get around this by using one of the other available adapters listed at https://lostisland.github.io/faraday/adapters/:
- https://lostisland.github.io/faraday/adapters/excon
- https://lostisland.github.io/faraday/adapters/patron
- https://lostisland.github.io/faraday/adapters/httpclient
Or external adapters that require another gem:
- https://github.com/typhoeus/typhoeus
- https://github.com/lostisland/faraday-http
Your specific implementation of Patron looks correct, so try using one of the other adapters to see if you have any better luck.
Update
I loaded your updated example and tested it myself. The solution is to use stringified keys. You're using symbolized keys.
# symbolized
headers = { API_SIGNATURE: '', API_REQUEST_TIME: '' }
=> {
:API_SIGNATURE => "",
:API_REQUEST_TIME => ""
}
This returns:
puts conn.headers
{"Api-Signature"=>"", "Api-Request-Time"=>"", "User-Agent"=>"Faraday v0.17.0"}
vs:
# stringified
headers = { 'API_SIGNATURE' => '', 'API_REQUEST_TIME' => '' }
=> {
"API_SIGNATURE" => "",
"API_REQUEST_TIME" => ""
}
Now you get the proper values:
puts conn.headers
{"API_SIGNATURE"=>"", "API_REQUEST_TIME"=>"", "User-Agent"=>"Faraday v0.17.0"}
At a glance, your original example appears stringified but is not (which is why I didn't catch it):
{
'API_SIGNATURE': '',
'API_REQUEST_TIME': ''
}
=> {
:API_SIGNATURE => "",
:API_REQUEST_TIME => ""
}
Using a colon for your hash key in Ruby automatically makes it a symbol, even if it's a quoted string. You need to use the hash rocket syntax for stringified keys.
来源:https://stackoverflow.com/questions/58458792/how-to-use-adapter-to-prevent-faraday-from-changing-capitalize-headers