2012-02-19 36 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