EOFError: problema de final de arquivo alcançado com Net :: HTTP

158

Estou usando o ruby-1.8.7-p302 / Rails 2.3.11. Estou tentando usar o FQL (API do Facebook) para obter estatísticas para um link. Aqui está o meu código:

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

E aqui está o erro:

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

Isso parece estar acontecendo apenas no caso da API do Facebook. Além disso, vi sugerido em algum post que poderia ser um bug no Net :: HTTP.

Rahul Singh
fonte
3
Você encontrou uma solução para isso? Estou enfrentando um problema semelhante na API SFDC.
Nilesh

Respostas:

280

Se o URL estiver usando https em vez de http, você precisará adicionar a seguinte linha:

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

Observe o adicional http.use_ssl = true.

E o código mais apropriado que lidaria com http e https será semelhante ao seguinte.

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)

Veja mais em meu blog: EOFError: problema de fim de arquivo atingido ao postar um formulário com Net :: HTTP .

Sur Max
fonte
Obrigado, isso me ajudou a entender a diferença entre o httpe req.
precisa saber é o seguinte
6
O link para post é quebrado, mas tente o seguinte: web.archive.org/web/20150429191916/http://expressica.com/2012/...
Henrik N
E se não for https?
precisa saber é o seguinte
5

Eu tive um problema semelhante com uma solicitação para um serviço não SSL.

Este blog sugeriu vagamente tentar codificar o URL que é passado para 'get': http://www.loudthinking.org/2010/02/ruby-eoferror-end-of-file-reached.html

Eu tentei, com base no desespero, e nos meus testes limitados isso parece ter resolvido isso para mim. Meu novo código é:

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

Observe que eu uso @ http.start como desejo manter a sessão HTTP em várias solicitações. Fora isso, você pode tentar a parte mais relevante que é: URI.encode (url) dentro da chamada get

Phil
fonte
2
Eu só queria fornecer um feedback adicional sobre isso, pois ainda parece útil. Estou em execução usando esse URI codificado em um servidor de produção há 4 meses e posso confirmar que ele corrigiu o problema.
31412 Phil
3

Acho que encontro problemas Net :: HTTP e Net :: FTP assim periodicamente e, quando o faço, cercar a chamada com um timeout () faz com que todos esses problemas desapareçam. Então, quando isso ocasionalmente travar por 3 minutos ou mais e, em seguida, gerar um erro EOFE:

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

Isso sempre corrige isso para mim:

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

Eu tive o mesmo problema, ruby-1.8.7-p357, e tentei muitas coisas em vão ...

Finalmente percebi que isso acontece apenas em várias chamadas usando a mesma instância XMLRPC :: Client!

Então agora estou re-instanciando meu cliente a cada chamada e ele simplesmente funciona: |

jobwat
fonte
1

Depois de fazer algumas pesquisas, isso estava acontecendo na XMLRPC::Clientbiblioteca do Ruby - que usa NET::HTTP. O cliente usa o start()método no NET::HTTPqual mantém a conexão aberta para solicitações futuras.

Isso aconteceu precisamente 30 segundos após as últimas solicitações - então minha suposição aqui é que o servidor que está atingindo está fechando as solicitações após esse período. Não sei ao certo qual é o padrão para NET::HTTPmanter a solicitação em aberto - mas estou prestes a testar com 60 segundos para ver se isso resolve o problema.

TJ Biddle
fonte
1
Qual foi o resultado?
22818 Peter Mortensen
1

Eu me deparei com isso recentemente e, eventualmente, descobri que isso foi causado por um tempo limite de rede do ponto de extremidade que estávamos atingindo. Felizmente para nós, conseguimos aumentar a duração do tempo limite.

Para verificar se esse era o nosso problema (e na verdade não era um problema com o http líquido), fiz a mesma solicitação com curl e confirmei que a solicitação estava sendo encerrada.

Tyler
fonte
-1

No Ruby on Rails, usei esse código, e ele funciona perfeitamente:

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é
fonte