EOFError: кінець файлу досягнуто проблеми з Net :: HTTP


158

Я використовую ruby-1.8.7-p302 / Rails 2.3.11. Я намагаюся використовувати FQL (Facebook API), щоб отримати статистику посилання. Ось мій код:

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

І ось помилка:

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

Це, мабуть, відбувається лише у випадку API Facebook. Також я бачив, що в якомусь дописі пропонується це може бути помилка в Net :: HTTP.


3
Ви знайшли рішення для цього? Я стикаюся з подібною проблемою в API SFDC.
Нілеш

Відповіді:


281

Якщо URL використовує https замість http, вам потрібно додати наступний рядок:

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

Зверніть увагу на додаткове http.use_ssl = true.

І більш відповідний код, який би обробляв і http, і https, буде подібний до наступного.

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

Дивіться більше в моєму блозі: EOFError: кінець файлу досягнуто проблеми під час публікації форми в мережі Net :: HTTP .


Дякую, це допомогло мені зрозуміти різницю між httpта req.
гуптрон

6
Посилання на щоденник блогу порушено, але спробуйте: web.archive.org/web/20150429191916/http://expressica.com/2012/…
Генрік N

Що робити, якщо це не https?
Jwan622

5

У мене була подібна проблема із запитом до служби, що не стосується SSL.

Цей блог запропонував невизначено спробувати URI, що кодує URL-адресу, передану "get": http://www.loudthinking.org/2010/02/ruby-eoferror-end-of-file-reached.html

Я зробив постріл у нього, грунтуючись на відчаї, і в моєму обмежувальному тестуванні, здається, це було виправлено для мене. Мій новий код:

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

Зауважте, що я використовую @ http.start, оскільки хочу підтримувати сеанс HTTP для кількох запитів. Крім цього, ви можете спробувати найбільш релевантну частину, яка є: URI.encode (url) всередині отримання дзвінка


2
Я просто хотів надати кілька додаткових відгуків щодо цього, оскільки це все ще здається корисним. Я використовую цей закодований URI на виробничому сервері протягом 4 місяців і можу підтвердити, що він усунув проблему.
Філ

3

Я вважаю, що я стикаюся з проблемами Net :: HTTP та Net :: FTP, як це періодично, і коли я це роблю, оточення виклику з таймаутом () змушує всі ці проблеми зникати. Тож де час від часу зависає 3 хвилини, а потім підніме EOFError:

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

Це завжди виправляє це для мене:

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

3

У мене була така ж проблема, як рубін-1.8.7-p357, і спробував безліч речей ...

Нарешті я зрозумів, що це відбувається лише при декількох викликах, використовуючи один і той же XMLRPC :: Клієнтський екземпляр!

Тож тепер я повторно інстатую мого клієнта під час кожного дзвінка, і він просто працює: |


1

Провівши деякі дослідження, це відбувалося в XMLRPC::Clientбібліотеці Рубі - яка використовує NET::HTTP. Клієнт використовує start()метод, в NET::HTTPякому зберігає з'єднання відкритим для майбутніх запитів.

Це сталося саме через 30 секунд після останніх запитів - тому моє припущення тут полягає в тому, що сервер, на який він звертається, закриває запити після цього часу. Я не впевнений, що за замовчуванням триває NET::HTTPзапит відкритим - але я збираюся перевірити 60 секунд, щоб побачити, чи вирішує це питання.


1
Яким був результат?
Пітер Мортенсен

1

Я нещодавно зіткнувся з цим і, врешті-решт, виявив, що це спричинено мережевим тайм-аутом від кінцевої точки, в яку ми потрапили. На щастя для нас, нам вдалося збільшити тривалість очікування.

Щоб переконатися, що це наша проблема (а насправді це не проблема з чистим http), я зробив той самий запит із завитком і підтвердив, що запит припиняється.


-1

У Ruby on Rails я використовував цей код, і він відмінно працює:

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']
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.