停止ruby http请求修改标题名称

pro*_*ach 6 ruby http

我在ruby中做一个http请求:

  http = Net::HTTP.new(uri.host, uri.port)
  req = Net::HTTP::Post.new(uri.path)
  req.body = payload
  req['customeheader'] = 'xxxxxxxxx'
  http.set_debug_output $stdout
Run Code Online (Sandbox Code Playgroud)

我打开了调试,当请求发布时,我可以看到标题被发布为:

  Customheader: xxxxxxxxx
Run Code Online (Sandbox Code Playgroud)

反正有没有阻止这个,我发布的第三方服务器发出错误,因为标题名称不正确 - 它正在期待 customheader:

Cor*_*rin 14

虽然可以通过修补Net :: HTTPHeader和Net:HTTPGenericRequest来删除小写和大写,但我发现了一种不同的方法,允许选择性区分大小写而不是强制一切.

解决方案:

class CaseSensitiveString < String
    def downcase
        self
    end
    def capitalize
        self
    end
end
Run Code Online (Sandbox Code Playgroud)

然后CaseSensitiveString.new('keyname')在区分大小写时创建密钥.将字符串/符号用于其他键以维护现有行为.这比猴子修补要简单得多,并且与rest-client库以及Net :: HTTP配合得很好.


Mar*_*mas 5

根据HTTP规范(RFC 2616),标头字段名称不区分大小写.因此第三方服务器的实现方式已损坏.

如果你真的需要,你可以修补Net :: HTTP以保留大小写,因为它在存储它们时会对字段名称进行下调,然后用初始大写字母写入它们.

这是您使用的存储方法(Net::HTTPHeader#[]=):

# File net/http.rb, line 1160
    def []=(key, val)
      unless val
        @header.delete key.downcase
        return val
      end
      @header[key.downcase] = [val]
    end
Run Code Online (Sandbox Code Playgroud)

这是写入header(Net::HTTPGenericRequest#write_header)的地方:

# File lib/net/http.rb, line 2071
    def write_header(sock, ver, path)
      buf = "#{@method} #{path} HTTP/#{ver}\r\n"
      each_capitalized do |k,v|
        buf << "#{k}: #{v}\r\n"
      end
      buf << "\r\n"
      sock.write buf
    end
Run Code Online (Sandbox Code Playgroud)

这些可能是您需要覆盖的唯一方法,但我并非100%肯定.


小智 5

基于之前的答案,这将适用于ruby 2.3:

class CaseSensitiveString < String
  def downcase
    self
  end

  def capitalize
    self
  end

  def to_s
    self
  end
end
Run Code Online (Sandbox Code Playgroud)

to_s方法需要添加因为2.3,HTTP::Headercapitalize方法调用to_s的每个标题.