You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用适配器阻止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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:21:01