2014-06-12 62 views
0

字符編碼時,我有這樣的HTTP請求:指定的Net :: HTTP

Net::HTTP.get_response('www.telize.com',"/geoip/190.88.39.27").body 
    => "{\"timezone\":\"America\\/Curacao\",\"isp\":\"United Telecommunication Services (UTS)\",\"country\":\"Cura\xE7ao\",\"dma_code\":\"0\",\"region_code\":\"00\",\"area_code\":\"0\",\"ip\":\"190.88.39.27\",\"asn\":\"AS11081\",\"continent_code\":\"NA\",\"city\":\"Willemstad\",\"longitude\":-68.9167,\"latitude\":12.1,\"country_code\":\"CW\",\"country_code3\":\"CUW\"}\n" 

它返回一個JSON的身體,但注意到國家:\ 「國家\」:\ 「庫拉\ xE7ao \」。響應機構應該看起來像這樣:「country」:「Curaçao」。它看起來像Net :: HTTP假設這是ASCII-8BIT:

Net::HTTP.get_response('www.telize.com',"/geoip/190.88.39.27").body.encoding 
=> Encoding:ASCII-8BIT 

但這不可能是這種情況。如何告知Net :: HTTP在發出請求時使用哪種字符編碼?

+0

您運行的是哪個版本的Ruby? –

回答

2

正如Tin Man所確定的,「\ xE7」是LATIN SMALL LETTER C WITH CEDILLA的latin-1編碼,就我所能確定的而言,它不是一個有效的json編碼。

require 'net/http' 

server_encoding = "ISO-8859-1" 
resp = Net::HTTP.get_response('www.telize.com',"/geoip/190.88.39.27") 
json = resp.body.force_encoding(server_encoding).encode("UTF-8") 
puts json 

--output:-- 

{"timezone":"America\/Curacao","isp":"United Telecommunication Services 
UTS)","country":"Curaçao","dma_code":"0","region_code":"00","area_code":"0", 
"ip":"190.88.39.27","asn":"AS11081","continent_code":"NA","city":"Willemstad", 
"longitude":-68.9167,"latitude":12.1,"country_code":"CW","country_code3":"CUW"} 

但是......一旦你知道了編碼,可以將其從Ruby的ASCII-8BIT(這只是意味着紅寶石認爲該數據爲二進制,即未編碼)以UTF-8,這樣的改變

它看起來像的Net :: HTTP是假設這是ASCII-8BIT

的Net :: HTTP變量的數據作爲二進制/ ASCII-8BIT,即數據沒有編碼,它留給你要弄清楚如何解釋數據。

+0

完美!我想我不得不告訴Net :: HTTP編碼是什麼,但沒有意識到我可以在事實後強制它。 –

+0

@Tom Rossi,您可能需要發送電子郵件至www.telize.com,並詢問他們爲什麼認爲latin-1是有效的json編碼。 – 7stud

1

你不能告訴服務器使用什麼編碼,但你可以問它它認爲文件的編碼是什麼,然後通過Net :: HTTP。

看那head方法:

response = nil 
Net::HTTP.start('www.telize.com',80) { |http| 
    response = http.head('/geoip/190.88.39.27') 
} 
response.each_header { |h| p "#{ h } => #{ response[h] }" } 

運行,告訴您不同標題的內容:

"server => nginx" 
"date => Thu, 12 Jun 2014 23:42:16 GMT" 
"content-type => application/json; charset=iso-8859-1" 
"connection => close" 

content-type值是你想要什麼:

response['content-type'].split('=').last 
# => "iso-8859-1" 

請注意,服務器很少執行一致性檢查以查看w不管它被告知使用的編碼是否與它所服務的文件匹配。這意味着您收到的內容可能會與服務器所說的內容大不相同,並且此時您完全依靠自己來弄清楚它的真實含義,尤其是當文件具有混合編碼時。歡迎來到野生和毛茸茸的互聯網。

+0

感謝您的幫助! –