ошибка open-uri с Zlib :: ошибка DataError: неправильная проверка данных

#ruby #zlib

#ruby #zlib

Вопрос:

У меня есть список URL-адресов изображений (> 1000), которые мне нужно загрузить в моем приложении ruby. Я использую open-uri для этого. Я знаю, что у него есть недостатки, но это удобно, если вам нужно поддерживать http, https и ftp.

Сам вызов так прост, как это

 file = open(url) # an https url
  

После этого файл обрабатывается с помощью Paperclip.

Проблема в том, что вызов время от времени завершается с ошибкой Zlib::DataError , даже при использовании одних и тех же URL-адресов снова и снова. Иногда их можно загрузить, иногда изображение выдает ошибку. Это трассировка стека:

 /usr/local/lib/ruby/2.6.0/net/http/response.rb:382 in inflate
/usr/local/lib/ruby/2.6.0/net/http/response.rb:382 in block in inflate_adapter
/usr/local/lib/ruby/2.6.0/net/protocol.rb:497 in call_block
/usr/local/lib/ruby/2.6.0/net/protocol.rb:488 in <<
/usr/local/lib/ruby/2.6.0/net/protocol.rb:163 in read
/usr/local/lib/ruby/2.6.0/net/http/response.rb:405 in read
/usr/local/lib/ruby/2.6.0/net/http/response.rb:293 in block in read_body_0
/usr/local/lib/ruby/2.6.0/net/http/response.rb:264 in inflater
/usr/local/lib/ruby/2.6.0/net/http/response.rb:283 in read_body_0
/usr/local/lib/ruby/2.6.0/net/http/response.rb:204 in read_body
/usr/local/lib/ruby/2.6.0/open-uri.rb:352 in block (2 levels) in open_http
/usr/local/lib/ruby/2.6.0/net/http.rb:1518 in block in transport_request
/usr/local/lib/ruby/2.6.0/net/http/response.rb:165 in reading_body
/usr/local/lib/ruby/2.6.0/net/http.rb:1517 in transport_request
/usr/local/lib/ruby/2.6.0/net/http.rb:1479 in request
/gems/newrelic_rpm-5.6.0.349/lib/new_relic/agent/instrumentation/net.rb:36 in block in request_with_newrelic_trace
/gems/newrelic_rpm-5.6.0.349/lib/new_relic/agent.rb:501 in disable_all_tracing
/gems/newrelic_rpm-5.6.0.349/lib/new_relic/agent/instrumentation/net.rb:35 in request_with_newrelic_trace
/gems/elastic-apm-2.3.1/lib/elastic_apm/spies/net_http.rb:54 in block in request
/gems/elastic-apm-2.3.1/lib/elastic_apm.rb:276 in with_span
/gems/elastic-apm-2.3.1/lib/elastic_apm/spies/net_http.rb:51 in request
/usr/local/lib/ruby/2.6.0/open-uri.rb:343 in block in open_http
/usr/local/lib/ruby/2.6.0/net/http.rb:920 in start
/usr/local/lib/ruby/2.6.0/open-uri.rb:337 in open_http
/usr/local/lib/ruby/2.6.0/open-uri.rb:756 in buffer_open
/usr/local/lib/ruby/2.6.0/open-uri.rb:226 in block in open_loop
/usr/local/lib/ruby/2.6.0/open-uri.rb:224 in catch
/usr/local/lib/ruby/2.6.0/open-uri.rb:224 in open_loop
/usr/local/lib/ruby/2.6.0/open-uri.rb:165 in open_uri
/usr/local/lib/ruby/2.6.0/open-uri.rb:736 in open
/usr/local/lib/ruby/2.6.0/open-uri.rb:35 in open
  

Я также загрузил изображения с помощью wget , чтобы посмотреть, отправляет ли сервер поврежденное изображение, но это сложно отлаживать: вы не можете быть уверены, все ли в порядке, потому что сервер не вернул ошибку при этом запуске, или просто с сервером все в порядке, и с ним нет ошибки.

Итак, я не уверен, вызвана ли ошибка сервером, или open-uri, или …?

Итак, чтобы лучше отладить эту проблему, я хочу понять, почему ruby http делает это inflate , и могу ли я обойти это, или кто-нибудь сталкивался с чем-то подобным раньше.

Комментарии:

1. Я предполагаю, что inflate метод используется для распаковки ответа с сервера (поскольку веб-серверы сжимают данные). Поскольку эта ошибка возникает случайным образом, это может быть несоответствие в ответе сервера.

2. но я не устанавливаю никаких заголовков, подобных Accept-Encoding: gzip,deflate в запросе. Или вы имеете в виду какое-то сжатие транспорта (а не сжатие содержимого)? Если да, можете ли вы уточнить?

3. Я обнаружил, что response.rb # L382 «Это позволяет раздувать большое тело ответа без сохранения всего тела в памяти.», и описание ошибки находится здесь «Обычно, если поток был преждевременно освобожден». Итак, кажется , что ошибка действительно на сервере, и в вашем коде я бы перехватил эту ошибку и повторил запрос с небольшим таймаутом.