使用Ruby的Net:HTTP保留HTTP头中的大小写

虽然HTTP规范说标题不区分大小写; Paypal及其新的自适应支付API要求其标题区分大小写。

使用ActiveMerchant的paypal自适应支付扩​​展( http://github.com/lamp/paypal_adaptive_gateway )似乎虽然标题是全部大写的,但它们是以大小写forms发送的。

以下是发送HTTP请求的代码:

headers = { "X-PAYPAL-REQUEST-DATA-FORMAT" => "XML", "X-PAYPAL-RESPONSE-DATA-FORMAT" => "JSON", "X-PAYPAL-SECURITY-USERID" => @config[:login], "X-PAYPAL-SECURITY-PASSWORD" => @config[:password], "X-PAYPAL-SECURITY-SIGNATURE" => @config[:signature], "X-PAYPAL-APPLICATION-ID" => @config[:appid] } build_url action request = Net::HTTP::Post.new(@url.path) request.body = @xml headers.each_pair { |k,v| request[k] = v } request.content_type = 'text/xml' proxy = Net::HTTP::Proxy("127.0.0.1", "60723") server = proxy.new(@url.host, 443) server.use_ssl = true server.start { |http| http.request(request) }.body 

(我添加了代理行,所以我可以看到Charles发生了什么 – http://www.charlesproxy.com/ )

当我查看查尔斯中的请求标头时,这就是我所看到的:

 X-Paypal-Application-Id ... X-Paypal-Security-Password... X-Paypal-Security-Signature ... X-Paypal-Security-Userid ... X-Paypal-Request-Data-Format XML X-Paypal-Response-Data-Format JSON Accept */* Content-Type text/xml Content-Length 522 Host svcs.sandbox.paypal.com 

我通过使用curl运行类似的请求来validationCharles不进行大小写转换。 在那次测试中,案件得以保留。

RFC确实指定标头密钥不区分大小写 ,所以不幸的是,您似乎遇到了PayPal API的烦人需求。

Net :: HTTP正在改变这种情况,虽然我很惊讶他们并没有全都变得沮丧:

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

“设置与不区分大小写的键对应的标题字段。”

由于上面是一个简单的类,它可能是猴子修补。 我会进一步思考一个更好的解决方案。

使用以下代码强制区分大小写的标头。

 class CaseSensitivePost < Net::HTTP::Post def initialize_http_header(headers) @header = {} headers.each{|k,v| @header[k.to_s] = [v] } end def [](name) @header[name.to_s] end def []=(name, val) if val @header[name.to_s] = [val] else @header.delete(name.to_s) end end def capitalize(name) name end end 

用法示例:

 post = CaseSensitivePost.new(url, {myCasedHeader: '1'}) post.body = body http = Net::HTTP.new(host, port) http.request(post)