6

我正在尝试使用 Gnip PowerTrack API,它要求我使用基本身份验证连接到 JSON 的 HTTPS 流。我觉得这应该是相当微不足道的,所以我希望一些比我聪明的 ruby​​ist 能指出我明显的错误。

这是我的 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 仪表板表示连接)但随后只是缓冲并且从不输出任何内容。事实上,它似乎永远不会进入s.stream do..区块。请注意,这是一个 GZip 编码流。

请注意,这有效:

curl --compressed -uusername $GNIP_STREAMING_URL

编辑:我确定这有点隐含,但我不能给出任何登录凭据或实际 URL,所以不要问;)

编辑#2:如果我能弄清楚如何为 URL 编码凭据,yajl-ruby 可能会起作用(简单的 URL 编码似乎不起作用,因为我无法通过 Gnip 进行身份验证)。

编辑#3:@rweald 发现 em-http 不支持流式 gzip,我在这里创建了一个 GitHub 问题。

编辑#4:我已经在 em-http-request 中分叉并修复了这个问题,如果你想以这种方式使用 em-http ,你可以指向我的分叉。该补丁已合并到维护者的存储库中,并将在下一个版本中使用。

编辑#5:我的修复程序已在 em-http-request 1.0.3 中发布,因此这应该不再是问题。

4

4 回答 4

2

问题在于 em-http-request。如果您查看 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

如果您希望能够使用 em-http-request 读取流,则需要修复底层流 gzip 问题

于 2012-02-22T05:13:20.953 回答
1

我一直在使用这个 Gist 的一些代码库来连接到 Gnip 控制台。 https://gist.github.com/1468622

于 2012-03-05T21:45:04.530 回答
0

看起来使用https://github.com/brianmario/yajl-ruby可以很好地解决这个问题

于 2012-02-21T22:21:34.773 回答
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

虽然我想要在连接断开时重新连接并优雅地处理不同类型的故障的东西。

于 2012-02-26T17:55:09.037 回答