2012-02-19 60 views
6

我試圖使用Gnip PowerTrack API,該API需要使用基本身份驗證連接到JSON的HTTPS流。我覺得這應該是相當微不足道的,所以我希望一些比我聰明的紅寶石主義者能指出我明顯的錯誤。具有基本身份驗證和gzip的em-http流程

下面是相關的部分我的Ruby 1.9.3代碼:

require 'eventmachine' 
require 'em-http' 
require 'json' 

usage = "#{$0} <user> <password>" 
abort usage unless user = ARGV.shift 
abort usage unless password = ARGV.shift 
GNIP_STREAMING_URL = 'https://stream.gnip.com:443/foo/bar/prod.json' 

http = EM::HttpRequest.new(GNIP_STREAMING_URL) 
EventMachine.run do 
    s = http.get(:head => { 'Authorization' => [user, password], 'accept' => 'application/json', 'Accept-Encoding' => 'gzip,deflate' }, :keepalive => true, :connect_timeout => 0, :inactivity_timeout => 0) 

    buffer = "" 
    s.stream do |chunk| 
    buffer << chunk 
    while line = buffer.slice!(/.+\r?\n/) 
     puts JSON.parse(line) 
    end 
    end 
end 

流連接(我的儀表盤GNIP一個repors連接),但是隻是緩存,從不輸出任何東西。實際上,它似乎從未進入s.stream do..區塊。請注意,這是一個GZip編碼流。

需要注意的是這個工程:

curl --compressed -uusername $GNIP_STREAMING_URL 

編輯:我敢肯定,這是有點含蓄,但我不能給任何登錄creds或實際的URL,所以不要問;)

編輯#2:yajl-ruby可能會工作,如果我能弄清楚如何編碼URL的憑據(簡單的URL編碼似乎不工作,因爲我無法使用Gnip身份驗證)。

編輯#3:@rweald發現em-http不支持串流gzip,我在這裏創建了一個GitHub問題。編輯#4:我已經在em-http-request中分叉並修復了這個問題,如果你想以這種方式使用em-http,你可以指向my fork。該補丁已合併到維護人員的回購中,並將在下一個版本中工作。

編輯#5:我的修復已發佈在em-http-request 1.0.3中,所以這應該不再是問題。

回答

2

問題在於EM-HTTP請求中。如果你看一下 https://github.com/igrigorik/em-http-request/blob/master/lib/em-http/decoders.rb

你會發現,gzip解壓縮做不到流減壓:( https://github.com/igrigorik/em-http-request/blob/master/lib/em-http/decoders.rb#L100

您將需要修復的基礎流gzip的問題,如果你想成爲能夠讀取流使用EM-HTTP請求

+0

很好找!也許我們修復em-http寶石。如果沒有,有沒有辦法使用yajl-ruby或者curb來保持連接存活,然後嘗試以指數回退模式重新連接? – 2012-02-22 14:02:01

+0

是的,所以我昨天發現了一個解決方法,它將允許從GNIP流式傳輸gzip json。我正在清理代碼,你將能夠在我的github項目中看到它https://github.com/rweald/gnip-stream – rweald 2012-02-23 16:00:32

+0

我想我應該能夠概括該修補程序以及它可以作爲補丁添加到em-http-request中。我會在週末看看。 – rweald 2012-02-23 16:01:33

0

它看起來像使用https://github.com/brianmario/yajl-ruby將解決這個很好

+0

它看起來很有希望,但我不知道如何編碼用戶名和密碼,以便我不會出現此錯誤:「lib/ruby​​/1.9.1/uri/generic.rb:411 :在'check_user':壞組件(預期的userinfo組件或用戶組件)「 – 2012-02-22 02:07:36

+1

這實際上也不會幫助。如果你看看http_request的yajl-ruby代碼,你會發現它只支持gzip,如果響應不是GNIP響應的「分塊」。 https://github.com/brianmario/yajl-ruby/blob/master/lib/yajl/http_stream.rb#L160 – rweald 2012-02-23 16:02:49

0

GNIP建議我用curb和這裏就是我想出了從他們的例子:

require 'rubygems' 
require 'curb' 

# Usage: <script> username password url 
# prints data to stdout. 
usage = "#{$0} <user> <password> <url>" 
username, password, url = ARGV.first 3 

Curl::Easy.http_get url do |c| 
    c.http_auth_types = :basic 
    c.username = username 
    c.password = password 
    c.encoding = 'gzip' 
    c.on_body do |data| 
    puts data 
    data.size # required by curl's api. 
    end 
end 

雖然我希望在連接斷開時重新連接,並且優雅地處理不同類型的故障。

1

我一直在使用這個Gist的一些代碼庫連接到Gnip控制檯。 https://gist.github.com/1468622

+0

謝謝!如果我早點發現,會節省很多時間,但我現在可以修補gnip-stream gem :) – 2012-03-06 02:01:05