EOFError: fin del archivo alcanzado problema con Net :: HTTP

158

Estoy usando ruby-1.8.7-p302 / Rails 2.3.11. Estoy tratando de usar FQL (Facebook API) para obtener estadísticas de un enlace. Aquí está mi 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

Y aquí está el error:

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

Esto parece estar sucediendo solo en el caso de la API de Facebook. Además, vi que sugería en alguna publicación que esto podría ser un error en Net :: HTTP.

Rahul Singh
fuente
3
¿Encontraste la solución para esto? Estoy enfrentando un problema similar en la API de SFDC.
Nilesh

Respuestas:

281

Si la URL usa https en lugar de http, debe agregar la siguiente línea:

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

Tenga en cuenta el adicional http.use_ssl = true.

Y el código más apropiado que manejaría tanto http como https será similar al siguiente.

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)

Vea más en mi blog: EOFError: se alcanzó el problema al final del archivo al publicar un formulario con Net :: HTTP .

Sur Max
fuente
Gracias, esto me ayudó a entender la diferencia entre el httpy req.
guptron
66
El enlace de la publicación del blog está roto, pero intente esto: web.archive.org/web/20150429191916/http://expressica.com/2012/…
Henrik N
¿Qué pasa si no es https?
Jwan622
5

Tuve un problema similar con una solicitud a un servicio que no es SSL.

Este blog sugirió vagamente intentar URI que codifica la URL que se pasa a 'get': http://www.loudthinking.org/2010/02/ruby-eoferror-end-of-file-reached.html

Lo intenté, basado en la desesperación, y en mis pruebas limitantes esto parece haberme solucionado. Mi nuevo código es:

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

Tenga en cuenta que uso @ http.start porque quiero mantener la sesión HTTP en varias solicitudes. Aparte de eso, es posible que desee probar la parte más relevante que es: URI.encode (url) dentro de la llamada get

Phil
fuente
2
Solo quería proporcionar algunos comentarios adicionales sobre esto, ya que todavía parece ser útil. He estado usando este URI codificado en un servidor de producción durante 4 meses y puedo confirmar que ha solucionado el problema.
Phil
3

Encuentro que me encuentro con Net :: HTTP y Net :: FTP problemas como este periódicamente, y cuando lo hago, rodear la llamada con un tiempo de espera () hace que todos esos problemas desaparezcan. Entonces, donde esto ocasionalmente se bloqueará durante 3 minutos más o menos y luego elevará un EOFError:

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

Esto siempre me lo arregla:

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

Tuve el mismo problema, ruby-1.8.7-p357, y probé muchas cosas en vano ...

¡Finalmente me di cuenta de que sucede solo en varias llamadas que usan la misma instancia XMLRPC :: Client!

Así que ahora vuelvo a crear instancias de mi cliente en cada llamada y simplemente funciona: |

Jobwat
fuente
1

Después de investigar un poco, esto sucedía en la XMLRPC::Clientbiblioteca de Ruby, que utiliza NET::HTTP. El cliente utiliza el start()método NET::HTTPque mantiene la conexión abierta para futuras solicitudes.

Esto sucedió exactamente a los 30 segundos después de las últimas solicitudes, por lo que supongo que el servidor al que está llegando está cerrando solicitudes después de ese momento. No estoy seguro de cuál es el valor predeterminado para NET::HTTPmantener abierta la solicitud, pero estoy a punto de probar con 60 segundos para ver si eso resuelve el problema.

TJ Biddle
fuente
1
¿Cuál fue el resultado?
Peter Mortensen
1

Me encontré con esto recientemente y finalmente descubrí que esto fue causado por un tiempo de espera de la red desde el punto final que estábamos alcanzando. Afortunadamente para nosotros pudimos aumentar la duración del tiempo de espera.

Para verificar que este era nuestro problema (y en realidad no era un problema con net http), hice la misma solicitud con curl y confirmó que la solicitud estaba siendo cancelada.

Tyler
fuente
-1

En Ruby on Rails utilicé este código, y funciona perfectamente:

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