2012-02-19 13 views
6

मैं जीएनआईपी पावरट्रैक एपीआई का उपभोग करने का प्रयास कर रहा हूं जिसके लिए मुझे मूल ऑथ के साथ JSON की HTTPS स्ट्रीम से कनेक्ट करने की आवश्यकता है। मुझे लगता है कि यह काफी मामूली होना चाहिए इसलिए मुझे आशा है कि कुछ रूबीस्ट जो मेरे से ज्यादा चालाक हैं, मेरी स्पष्ट गलती को इंगित कर सकते हैं।मूल ऑथ और gzip hangs के साथ em-http स्ट्रीम

यहाँ प्रासंगिक भागों मेरी रूबी 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: यजल-रूबी शायद काम करेगा अगर मैं यूआरएल के लिए क्रेडेंशियल्स को एन्कोड करने का तरीका समझ सकता हूं (सरल यूआरएल एन्कोडिंग काम नहीं कर रहा है क्योंकि मैं जीएनआईपी के साथ प्रमाणीकरण विफल करता हूं)।

संपादित करें # 3: @ रिवाल्ड ने पाया कि em-http स्ट्रीमिंग gzip का समर्थन नहीं करता है, मैंने यहां एक गिटहब समस्या बनाई है।

संपादित करें # 4: मैंने इसे em-http-request में फोर्क किया है और इसे ठीक किया है, यदि आप इस तरह से em-http का उपयोग करना चाहते हैं तो आप my fork पर इंगित कर सकते हैं। पैच को रखरखाव के रेपो में विलय कर दिया गया है और अगली रिलीज में काम करेगा।

संपादित करें # 5: मेरे फिक्सेस em-http-request 1.0.3 में प्रकाशित किए गए हैं, इसलिए यह अब कोई समस्या नहीं होनी चाहिए।

उत्तर

2

समस्या उन्हें-http-अनुरोध के भीतर निहित है की तरह लग रहा है। आप https://github.com/igrigorik/em-http-request/blob/master/lib/em-http/decoders.rb

को देखें, तो आप देखेंगे कि GZIP decompressor स्ट्रीमिंग विसंपीड़न :(ऐसा नहीं कर सकते https://github.com/igrigorik/em-http-request/blob/master/lib/em-http/decoders.rb#L100

यदि आप एक धारा को पढ़ने में सक्षम होना चाहते थे आप अंतर्निहित स्ट्रीमिंग gzip समस्या को ठीक करने की आवश्यकता होगी उन्हें-http अनुरोध

+0

अच्छा लगता है!शायद हम em-http मणि को ठीक करते हैं। यदि नहीं, तो कनेक्शन को जीवित रखने के लिए yajl-ruby या curb का उपयोग करने का कोई तरीका है और फिर घातीय बैकऑफ पैटर्न में पुनः कनेक्ट करने का प्रयास करें? –

+0

हाँ तो मुझे वास्तव में कल एक कामकाज मिला जो जीएनआईपी से जीजीआईपी जेसन स्ट्रीमिंग की अनुमति देगा। मैं अब कोड को साफ करने पर काम कर रहा हूं और आप इसे अपने जीथब प्रोजेक्ट में देख पाएंगे https://github.com/rweald/gnip-stream – rweald

+0

मुझे लगता है कि मुझे फिक्स को सामान्यीकृत करने में सक्षम होना चाहिए ताकि यह em-http-request में पैच के रूप में जोड़ा जा सकता है। मैं सप्ताहांत पर एक नज़र डालेगा। – rweald

0

यह https://github.com/brianmario/yajl-ruby का उपयोग कर हल किया इस अच्छी तरह से

+0

यह आशाजनक लग रहा था, लेकिन मैं यह नहीं समझ सकता कि उपयोगकर्ता नाम और पासवर्ड को एन्कोड कैसे किया जाए, मुझे यह त्रुटि नहीं मिलती: "lib/ruby ​​/ 1.9.1/uri/generic.rb: 411 : 'check_user' में: खराब घटक (अपेक्षित userinfo घटक या उपयोगकर्ता घटक) " –

+1

यह वास्तव में या तो मदद नहीं करेगा। यदि आप http_request के लिए yajl-ruby कोड देखते हैं तो आप देखेंगे कि यह केवल gzip का समर्थन करता है अगर प्रतिक्रिया "चंक" नहीं है जो जीएनआईपी प्रतिक्रिया है। https://github.com/brianmario/yajl-ruby/blob/master/lib/yajl/http_stream.rb#L160 – rweald

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

मैं जीनिप कंसोल से कनेक्ट करने के लिए इस गिस्ट के कुछ कोड बेस का उपयोग कर रहा हूं। https://gist.github.com/1468622

+0

धन्यवाद! मैंने पहले इतना समय बचाया होगा, लेकिन मैं अब gnip-stream मणि पैच करने में सक्षम हो सकता है :) –