EOFError: wystąpił problem z końcem pliku z Net :: HTTP

158

Używam Ruby-1.8.7-p302 / Rails 2.3.11. Próbuję użyć FQL (Facebook API), aby uzyskać statystyki dla linku. Oto mój kod:

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

A oto błąd:

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

Wydaje się, że dzieje się tak tylko w przypadku API Facebooka. Widziałem również, że w pewnym poście zasugerowano, że może to być błąd w Net :: HTTP.

Rahul Singh
źródło
3
Czy znalazłeś rozwiązanie tego problemu? Mam podobny problem w SFDC API.
Nilesh

Odpowiedzi:

281

Jeśli adres URL używa https zamiast http, musisz dodać następujący wiersz:

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

Zwróć uwagę na dodatkowe http.use_ssl = true.

Bardziej odpowiedni kod, który obsługuje zarówno http, jak i https, będzie podobny do poniższego.

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)

Zobacz więcej na moim blogu: EOFError: problem z końcem pliku osiągnięty podczas wysyłania formularza z Net :: HTTP .

Sur Max
źródło
Dzięki, to pomogło mi zrozumieć różnicę między httpi req.
guptron
6
Link do wpisu na blogu jest uszkodzony, ale spróbuj tego: web.archive.org/web/20150429191916/http://expressica.com/2012/…
Henrik N
A jeśli to nie jest https?
Jwan622
5

Miałem podobny problem z żądaniem do usługi bez SSL.

Ten blog sugerował niejasno wypróbowanie kodowania URI adresu URL przekazywanego do „get”: http://www.loudthinking.org/2010/02/ruby-eoferror-end-of-file-reached.html

Podjąłem próbę, opierając się na desperacji, iw moich ograniczających testach wydaje się, że to naprawiło. Mój nowy kod to:

@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) 

Zauważ, że używam @ http.start, ponieważ chcę utrzymać sesję HTTP dla wielu żądań. Poza tym możesz wypróbować najbardziej odpowiednią część, która jest: URI.encode (url) w wywołaniu get

Phil
źródło
2
Chciałem tylko przekazać dodatkowe uwagi na ten temat, ponieważ nadal wydaje się to przydatne. Używam tego zakodowanego identyfikatora URI na serwerze produkcyjnym od 4 miesięcy i mogę potwierdzić, że rozwiązało to problem.
Phil
3

Okazało się, że okresowo napotykam problemy z Net :: HTTP i Net :: FTP, a kiedy to robię, otoczenie wywołania timeout () powoduje, że wszystkie te problemy znikają. Więc jeśli to czasami zawiesza się na około 3 minuty, a następnie podnosi EOFError:

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

To zawsze rozwiązuje problem:

res = timeout(120) { Net::HTTP.post_form(uri, args) }
Sean
źródło
3

Miałem ten sam problem, ruby-1.8.7-p357 i próbowałem wielu rzeczy na próżno ...

W końcu zdałem sobie sprawę, że dzieje się to tylko w przypadku wielu wywołań przy użyciu tej samej instancji XMLRPC :: Client!

Więc teraz ponownie tworzę instancję klienta przy każdym połączeniu i to po prostu działa: |

jobwat
źródło
1

Po przeprowadzeniu pewnych badań działo się to w XMLRPC::Clientbibliotece Rubiego - która używa NET::HTTP. Klient używa start()metody, w NET::HTTPktórej połączenie pozostaje otwarte dla przyszłych żądań.

Stało się to dokładnie po 30 sekundach od ostatniego żądania - więc zakładam, że serwer, na który trafia, zamyka żądania po tym czasie. Nie jestem pewien, jakie jest domyślne ustawienie, NET::HTTPaby żądanie pozostało otwarte - ale mam zamiar przetestować przez 60 sekund, aby sprawdzić, czy to rozwiązuje problem.

TJ Biddle
źródło
1
Jaki był rezultat?
Peter Mortensen
1

Niedawno natknąłem się na to i ostatecznie odkryłem, że było to spowodowane przekroczeniem limitu czasu sieci z punktu końcowego, na który trafiliśmy. Na szczęście dla nas udało nam się wydłużyć czas oczekiwania.

Aby sprawdzić, czy to nasz problem (a właściwie nie jest to problem z net http), wysłałem to samo żądanie z curl i potwierdziłem, że żądanie zostało zakończone.

Tyler
źródło
-1

W Ruby on Rails użyłem tego kodu i działa idealnie:

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é
źródło