EOFError: Ende der Datei erreicht Problem mit Net :: HTTP

158

Ich verwende Ruby-1.8.7-p302 / Rails 2.3.11. Ich versuche, FQL (Facebook API) zu verwenden, um Statistiken für einen Link zu erhalten. Hier ist mein Code:

def stats(fb_post_url)
  url = BASE_URI + "?query=#{URI.encode("select like_count from link_stat where url=\"#{fb_post_url}\"")}"
  parsed_url = URI.parse(url)
  http = Net::HTTP.new(parsed_url.host, parsed_url.port)
  request = Net::HTTP::Get.new(parsed_url.request_uri)

  response = http.request(request)
  response.inspect
end

Und hier ist der Fehler:

EOFError: end of file reached
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/protocol.rb:135:in `sysread'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/protocol.rb:135:in `rbuf_fill'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/timeout.rb:67:in `timeout'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/timeout.rb:101:in `timeout'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/protocol.rb:134:in `rbuf_fill'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/protocol.rb:116:in `readuntil'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/protocol.rb:126:in `readline'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/http.rb:2028:in `read_status_line'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/http.rb:2017:in `read_new'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/http.rb:1051:in `request'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/http.rb:1037:in `request'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/http.rb:543:in `start'
from /home/rahul/.rvm/rubies/ruby-1.8.7-p302/lib/ruby/1.8/net/http.rb:1035:in `request'
from /home/rahul/Work/Radr/lib/fb_stats.rb:13:in `stats'
from (irb):10

Dies scheint nur im Fall der Facebook-API zu geschehen. Außerdem habe ich in einigen Beiträgen gesehen, dass dies ein Fehler in Net :: HTTP sein könnte.

Rahul Singh
quelle
3
Haben Sie eine Lösung dafür gefunden? Ich habe ein ähnliches Problem in der SFDC-API.
Nilesh

Antworten:

280

Wenn die URL https anstelle von http verwendet, müssen Sie die folgende Zeile hinzufügen:

parsed_url = URI.parse(url)
http = Net::HTTP.new(parsed_url.host, parsed_url.port)
http.use_ssl = true

Beachten Sie die zusätzlichen http.use_ssl = true.

Der geeignetere Code, der sowohl http als auch https verarbeitet, ähnelt dem folgenden.

url = URI.parse(domain)
req = Net::HTTP::Post.new(url.request_uri)
req.set_form_data({'name'=>'Sur Max', 'email'=>'[email protected]'})
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = (url.scheme == "https")
response = http.request(req)

Weitere Informationen finden Sie in meinem Blog: EOFError: Problem beim Ende der Datei erreicht, wenn ein Formular mit Net :: HTTP veröffentlicht wird .

Sur max
quelle
Danke, das hat mir geholfen, den Unterschied zwischen httpund zu verstehen req.
Guptron
6
Der Link zum Blog-Beitrag ist defekt, aber versuchen Sie Folgendes
Henrik N
Was ist, wenn es nicht https ist?
Jwan622
5

Ich hatte ein ähnliches Problem mit einer Anfrage an einen Nicht-SSL-Dienst.

In diesem Blog wurde vage vorgeschlagen, die URI-Codierung der URL zu versuchen, die an 'get' übergeben wird: http://www.loudthinking.org/2010/02/ruby-eoferror-end-of-file-reached.html

Ich habe aus Verzweiflung einen Versuch unternommen, und in meinen einschränkenden Tests scheint dies das Problem für mich behoben zu haben. Mein neuer Code lautet:

@http = Net::HTTP.new('domain.com')  
@http = @http.start    
url = 'http://domain.com/requested_url?blah=blah&etc=1'
req = Net::HTTP::Get.new(URI.encode(url))
req.basic_auth USERNAME, API_KEY
res = @http.request(req) 

Beachten Sie, dass ich @ http.start verwende, um die HTTP-Sitzung über mehrere Anforderungen hinweg aufrechtzuerhalten. Ansonsten möchten Sie vielleicht den relevantesten Teil ausprobieren, nämlich: URI.encode (url) innerhalb des get-Aufrufs

Phil
quelle
2
Ich wollte nur ein zusätzliches Feedback dazu geben, da es immer noch nützlich zu sein scheint. Ich verwende diesen codierten URI seit 4 Monaten auf einem Produktionsserver und kann bestätigen, dass das Problem behoben wurde.
Phil
3

Ich stelle fest, dass ich in regelmäßigen Abständen auf solche Net :: HTTP- und Net :: FTP-Probleme stoße. Wenn ich dies tue, verschwinden all diese Probleme, wenn ich den Aufruf mit einem Timeout () umgeben habe. Wo dies also gelegentlich etwa 3 Minuten lang hängt und dann einen EOFError auslöst:

res = Net::HTTP.post_form(uri, args)

Das behebt es immer für mich:

res = timeout(120) { Net::HTTP.post_form(uri, args) }
Sean
quelle
3

Ich hatte das gleiche Problem, ruby-1.8.7-p357, und habe viele Dinge vergeblich ausprobiert ...

Endlich wurde mir klar, dass dies nur bei mehreren Aufrufen mit derselben XMLRPC :: Client-Instanz geschieht!

Jetzt instanziiere ich meinen Client bei jedem Anruf neu und es funktioniert einfach: |

jobwat
quelle
1

Nach einigen Recherchen geschah dies in Rubys XMLRPC::ClientBibliothek - die verwendet NET::HTTP. Der Client verwendet die start()Methode, mit NET::HTTPder die Verbindung für zukünftige Anforderungen geöffnet bleibt.

Dies geschah genau 30 Sekunden nach den letzten Anforderungen. Daher gehe ich hier davon aus, dass der Server, auf den er trifft, Anforderungen nach dieser Zeit schließt. Ich bin nicht sicher, wie die Standardeinstellung verwendet werden soll NET::HTTP, um die Anforderung offen zu halten. Ich werde jedoch 60 Sekunden lang testen, um festzustellen, ob das Problem dadurch behoben wird.

TJ Biddle
quelle
1
Was war das Ergebnis?
Peter Mortensen
1

Ich bin kürzlich darauf gestoßen und habe schließlich festgestellt, dass dies durch ein Netzwerk-Timeout vom Endpunkt, den wir erreicht haben, verursacht wurde. Zum Glück konnten wir die Timeout-Dauer verlängern.

Um zu überprüfen, ob dies unser Problem war (und eigentlich kein Problem mit net http), habe ich dieselbe Anfrage mit curl gestellt und bestätigt, dass die Anfrage beendet wurde.

Tyler
quelle
-1

In Ruby on Rails habe ich diesen Code verwendet und er funktioniert perfekt:

req_profilepic = ActiveSupport::JSON.decode(open(URI.encode("https://graph.facebook.com/me/?fields=picture&type=large&access_token=#{fb_access_token}")))

profilepic_url = req_profilepic['picture']
Nicolas Grenié
quelle