[英]Preserving case in HTTP headers with Ruby's Net:HTTP
盡管 HTTP 規范說標頭不區分大小寫; Paypal 及其新的自適應支付 API 要求其標頭區分大小寫。
使用 ActiveMerchant ( http://github.com/lamp/paypal_adaptive_gateway ) 的 paypal 自適應支付擴展似乎雖然標題設置為全部大寫,但它們以混合大小寫發送。
這是發送 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/ )
當我查看 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 進行大小寫轉換。 在那個測試中,這個案例被保留了下來。
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)
我在@kaplan-ilya 提出的代碼中遇到了幾個問題,因為 Net::HTTP 庫試圖檢測帖子內容類型,而我最終得到了 2 個內容類型和其他字段,這些字段在不同情況下重復。
所以下面的代碼應該確保一旦選擇了一個特定的案例,它就會堅持下去。
class Post < Net::HTTP::Post
def initialize_http_header(headers)
@header = {}
headers.each { |k, v| @header[k.to_s] = [v] }
end
def [](name)
_k, val = header_insensitive_match name
val
end
def []=(name, val)
key, _val = header_insensitive_match name
key = name if key.nil?
if val
@header[key] = [val]
else
@header.delete(key)
end
end
def capitalize(name)
name
end
def header_insensitive_match(name)
@header.find { |key, _value| key.match Regexp.new(name.to_s, Regexp::IGNORECASE) }
end
end
如果您仍在尋找有效的答案。 較新的版本通過使用to_s
對底層的capitalize
方法進行了一些更改。 修復是讓to_s
和to_str
返回self
以便返回的對象是ImmutableKey
的實例而不是基字符串類。
class ImmutableKey < String
def capitalize
self
end
def to_s
self
end
alias_method :to_str, :to_s
end
參考: https : //jatindhankhar.in/blog/custom-http-header-and-ruby-standard-library/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.