2010-04-25 98 views
3

儘管HTTP規範指出標頭不區分大小寫, Paypal和他們的新適應性支付API要求他們的頭文件區分大小寫。使用Ruby's Net保留HTTP標頭中的大小寫:HTTP

使用適用於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 

(我加了代理行,所以我可以看到發生了什麼事情與查爾斯 - 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了類似的請求的情況下轉換。在那次測試中,案件得以保留。

回答

2

RFC確實指出標題密鑰是case-insensitive,所以不幸的是,您似乎已經遇到了PayPal API惱人的要求。

的Net :: HTTP是什麼正在發生變化的情況下,雖然我很驚訝他們是不是所有得到downcased:

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

「設定對應於不區分大小寫的鍵頭字段。」

由於上面是一個簡單的類,它可以被猴子修補。我會進一步思考一個更好的解決方案。

+0

是啊,猴子修補是一種選擇,而是你必須猴修補了很多比[] =方法......至少,[ ]和write_header也必須打補丁(後者是輸出時大寫字母的地方)。 – emh 2010-04-26 17:14:07

+1

請參閱此問題的答案:http://stackoverflow.com/questions/8864627/how-do-i-preserve-case-with-http-get – codingFoo 2012-12-04 00:02:08

+1

真正的罪魁禍首是Net :: HTTPHeader#capitalize – 2013-09-26 14:30:02

1

使用以下代碼強制區分大小寫的標題。

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)