Ruby: прервать OpenURI на основе длины контента

OpenURI Ruby предоставляет опция content_length_proc, которая позволяет определить* длину контента до начала фактической передачи:

open(url, :content_length_proc => lambda { |content_length|
  puts "Content Length: #{content_length}"
}) { |data|
   # data.meta, data.read etc.
}

Есть ли способ для этого процесса прервать фактическое полное извлечение?

* Я знаю, что это ненадежно, но в моем случае этого достаточно для простой эвристики.


person AnC    schedule 11.08.2011    source источник
comment
FWIW, оп заметил, что content-length ненадежен. Надежным подходом является использование :progress_proc, которое будет сообщать общее количество байтов каждый раз, когда новый блок вытягивается из сети. Таким образом, вы можете прервать, если вы получите слишком много данных на основе фактически загруженных байтов.   -  person Dan    schedule 29.07.2015


Ответы (1)


Это соответствующий код из open-uri.rb:

if options[:content_length_proc] && Net::HTTPSuccess === resp
  if resp.key?('Content-Length')
    options[:content_length_proc].call(resp['Content-Length'].to_i)
  else
    options[:content_length_proc].call(nil)
  end
end
resp.read_body {|str|
  ...
}

Как видите, возвращаемое значение content_length_proc игнорируется. Но то, что вы могли бы просто сделать, чтобы отменить операцию, - это вызвать некоторую форму ошибки в обратном вызове - это фактически прервет дальнейшее выполнение. Если вы создадите специальный класс ошибок, вы можете даже спасти его и отреагировать на эту конкретную ситуацию:

begin
  open(url, :content_length_proc => lambda { |content_length|
    puts "Content Length: #{content_length}"
  }) { |data|
    # data.meta, data.read etc.
  }
rescue MyError
  # react to it
end
person emboss    schedule 11.08.2011