使用 Ruby 的 Net:HTTP 保留 HTTP 标头中的大小写
尽管 HTTP 规范规定标头不区分大小写; Paypal 及其新的自适应支付 API 要求其标头区分大小写。
使用 ActiveMerchant 的 paypal 自适应支付扩展 (http://github.com/lamp/paypal_adaptive_gateway) 似乎尽管标头设置为全部大写,但它们是以混合大小写形式发送的。
下面是发送 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/)
当我查看 charles 中的请求标头时,我看到的是:
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 运行类似的请求来验证不是 Charles 进行大小写转换。在那次测试中,箱子被保存下来。
Although the HTTP spec says that headers are case insensitive; Paypal, with their new adaptive payments API require their headers to be case-sensitive.
Using the paypal adaptive payments extension for ActiveMerchant (http://github.com/lamp/paypal_adaptive_gateway) it seems that although the headers are set in all caps, they are sent in mixed case.
Here is the code that sends the HTTP request:
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
(i added the proxy line so i could see what was going on with Charles - http://www.charlesproxy.com/)
When I look at the request headers in charles, this is what i see:
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
I verified that it is not Charles doing the case conversion by running a similar request using curl. In that test the case was preserved.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
RFC 确实指定标头键不区分大小写,很遗憾,您似乎遇到了 PayPal API 的烦人要求。
Net::HTTP 正在改变这种情况,尽管我很惊讶它们并没有全部变成小写:
“设置与不区分大小写的密钥相对应的标头字段。”
由于上面是一个简单的类,因此可以对其进行猴子修补。我会进一步思考更好的解决方案。
The RFC does specify that header keys are case-insensitive, so unfortunately you seem to have hit an annoying requirement with the PayPal API.
Net::HTTP is what is changing the case, although I'm surprised they're not all getting downcased:
"Sets the header field corresponding to the case-insensitive key."
As the above is a simple class it could be monkey-patched. I will think further for a nicer solution.
使用以下代码强制区分大小写标头。
使用示例:
Use following code to force case sensitive headers.
Usage example:
如果您仍在寻找有效的答案。新版本通过使用
to_s
对底层capitalize
方法进行了一些更改。修复方法是让to_s
和to_str
返回self
,以便返回的对象是ImmutableKey
的实例基字符串类的。参考:https://jatindhankhar.in/blog/custom -http-header-and-ruby-standard-library/
If you are still looking for an answer that works. Newer versions have introduced some changes to underlying
capitalize
method by usingto_s
. Fix is to make theto_s
andto_str
return theself
so that the returned object is an instance ofImmutableKey
instead of the base string class.Ref: https://jatindhankhar.in/blog/custom-http-header-and-ruby-standard-library/
我遇到了 @kaplan-ilya 提出的代码的几个问题,因为 Net::HTTP 库尝试检测帖子内容类型,并且我最终得到了 2 个内容类型和其他在不同情况下重复的字段。
因此,下面的代码应该确保一旦选择了特定情况,它将坚持相同的情况。
I got several issues with the code proposed by @kaplan-ilya because the Net::HTTP library tries to detect the post content-type, and the I ended up with 2 content-type and other fields repeated with different cases.
So the code below should ensure than once a particular case has been choosen, it will stick to the same.