6

Estoy intentando consumir la API de Gnip PowerTrack que me requiere conectarme a una transmisión HTTPS de JSON con autenticación básica. Siento que esto debería ser bastante trivial, así que espero que algún rubí que sea más inteligente que yo pueda señalar mi obvio error.secuencia em-http con autenticación básica y gzip cuelga

Aquí hay partes pertinentes mi rubí 1.9.3 Código:

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 

se conecta la corriente (Mi tablero Gnip repors una conexión), pero luego sólo tampones y nunca da salida a nada. De hecho, parece que nunca entra en el bloque s.stream do... Tenga en cuenta que esta es una secuencia codificada GZip.

Tenga en cuenta que esto funciona:

curl --compressed -uusername $GNIP_STREAMING_URL 

EDIT: Estoy seguro de que esto es algo implícito, pero no puedo dar ninguna creds de inicio de sesión o la dirección URL real, así que no pregunte;)

EDIT # 2: yajl-ruby probablemente funcionaría si pudiera averiguar cómo codificar las credenciales para la URL (la simple codificación URL no parece funcionar ya que fallo en la autenticación con Gnip).

EDIT # 3: @rweald descubrió que em-http no es compatible con la transmisión de gzip, aquí he creado un problema de GitHub.

EDIT # 4: He bifurcado y reparado esto en em-http-request, puede marcar my fork si desea usar em-http de esta manera. El parche se fusionó con el repositorio del mantenedor y estará funcionando en la próxima versión.

EDIT # 5: Mis correcciones se han publicado en em-http-request 1.0.3, por lo que ya no debería ser un problema.

Respuesta

2

El problema se encuentra dentro de em-petición http. Si nos fijamos en https://github.com/igrigorik/em-http-request/blob/master/lib/em-http/decoders.rb

Usted se dará cuenta de que el descompresor GZIP no puede hacer streaming de descompresión :( https://github.com/igrigorik/em-http-request/blob/master/lib/em-http/decoders.rb#L100

Usted tendría que solucionar el problema de streaming gzip subyacente si desea ser capaz de leer una secuencia utilizando em-petición http

+0

¡Bonito hallazgo!Quizás arreglemos la gema em-http. Si no, ¿hay alguna manera de usar yajl-ruby o bordillo para mantener viva la conexión y luego intentar volver a conectar en un patrón de retroceso exponencial? –

+0

Sí, así que en realidad encontré una solución alternativa ayer que permitirá la transmisión de gzip json desde GNIP. Estoy trabajando en la limpieza del código ahora y podrás verlo en mi proyecto github https://github.com/rweald/gnip-stream – rweald

+0

Creo que debería poder generalizar la corrección también para que podría agregarse como un parche a em-http-request. Voy a echar un vistazo durante el fin de semana. – rweald

0

se ve como el uso de https://github.com/brianmario/yajl-ruby resolvería esta muy bien

+0

Parecía prometedor, pero no puedo descifrar cómo codificar el nombre de usuario y la contraseña de modo que no aparece este error: "lib/ruby ​​/ 1.9.1/uri/generic.rb: 411 : en 'check_user ': componente defectuoso (componente de userinfo esperado o componente de usuario)" –

+1

Esto en realidad tampoco servirá de nada. Si miras el código de yajl-ruby para http_request, notarás que solo soporta gzip si la respuesta no es "Chunked", que es la respuesta GNIP. https://github.com/brianmario/yajl-ruby/blob/master/lib/yajl/http_stream.rb#L160 – rweald

0

Gnip sugirió que usara curb y esto es lo que ocurrió con su ejemplo:

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 

Aunque me gustaría algo que se vuelva a conectar cuando se interrumpa la conexión y maneje diferentes tipos de fallas con elegancia.

1

He estado utilizando algunos códigos base de este Gist para conectarme a la consola Gnip. https://gist.github.com/1468622

+0

Gracias! Me habría ahorrado tanto tiempo si hubiera encontrado eso antes, pero es posible que pueda parchar la gema gnip-stream ahora :) –

Cuestiones relacionadas