如何使用适配器阻止Faraday自动转换请求头大小写?
解决Faraday自动转换请求头大小写及Patron超时问题
首先,Faraday默认会通过Faraday::Utils::Headers把下划线分隔的符号键转换成短横线分隔的驼峰式请求头(比如API_SIGNATURE会变成Api-Signature),这是它遵循HTTP头常规命名规范的默认行为,但有些API要求严格保留原始的大写下划线格式。下面给你几个可靠的解决方案,同时避开Patron适配器的超时坑:
方案一:用字符串作为请求头键 + 禁用头转换中间件
Faraday对字符串类型的头键处理会更宽松,搭配禁用默认的头转换中间件,就能完美保留原始头格式:
class APIClient BASE_API_URL = "https://api.test.io" def initialize(api_key) @api_key = api_key end def get_users connection.post('/users') end private def connection Faraday.new(BASE_API_URL) do |faraday| # 禁用自动转换头格式的中间件 faraday.request :headers, flat_encode: true # 直接传入字符串格式的请求头 faraday.headers.merge!(headers) # 用默认的Net::HTTP适配器替代Patron,稳定性更强 faraday.adapter :net_http end end def headers timestamp = Time.now.to_i.to_s { 'API_SIGNATURE' => Digest::MD5.hexdigest(@api_key + timestamp), 'API_REQUEST_TIME' => timestamp } end end
这里的核心要点:
- 用字符串作为请求头的键,不要用符号(符号会被Faraday自动格式化)
flat_encode: true参数告诉Headers中间件不要对键做大小写转换和格式调整- 替换成默认的
:net_http适配器,彻底避开Patron的超时兼容性问题
方案二:直接配置Net::HTTP适配器强制保留头格式
如果你想更精准控制Net::HTTP的行为,也可以直接通过适配器配置来确保头的原始格式:
def connection Faraday.new(BASE_API_URL) do |faraday| faraday.adapter :net_http do |http| # 根据API的SSL要求调整验证模式 http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.use_ssl = true if BASE_API_URL.start_with?('https') # Net::HTTP默认会调整头的大小写,但我们用字符串键+flat_encode已经能绕过这个问题 end faraday.request :headers, flat_encode: true faraday.headers.merge!(headers) end end
关于Patron适配器的超时问题
Patron是基于libcurl的适配器,超时通常和这几个因素有关:
- 网络环境限制(比如代理、防火墙拦截)
- 默认超时时间过短(默认仅1秒),可以手动调整试试:
def connection Faraday.new(BASE_API_URL, headers: headers) do |faraday| faraday.adapter :patron do |session| session.timeout = 10 # 设置10秒请求超时 session.connect_timeout = 5 # 设置5秒连接超时 end end end
但即使调整了超时,Patron对HTTP头的处理还是可能不符合你的需求,所以还是更推荐用Net::HTTP的方案。
验证请求头是否正确发送
可以加一个日志中间件来确认头的格式是否正确:
faraday.response :logger do |logger| # 过滤敏感的签名信息,避免日志泄露 logger.filter(/(API_SIGNATURE:).*/, '\1 [FILTERED]') end
运行代码后查看日志,就能确认API_SIGNATURE和API_REQUEST_TIME是不是以你想要的格式发送的。
内容的提问来源于stack exchange,提问作者user12212177
相关产品推荐
相关产品推荐

