From 637fd0bff5718f71f201e7b440d760acef9c18d4 Mon Sep 17 00:00:00 2001 From: Art Rybalko Date: Fri, 1 Aug 2025 18:23:56 +0300 Subject: [PATCH] Handle 3xx redirects differently when streaming --- lib/down/httpx.rb | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/down/httpx.rb b/lib/down/httpx.rb index 73a60ac..6ad5d3f 100644 --- a/lib/down/httpx.rb +++ b/lib/down/httpx.rb @@ -33,7 +33,7 @@ def initialize(**options, &block) end - # Downlods the remote file to disk. Accepts HTTPX options via a hash or a + # Downloads the remote file to disk. Accepts HTTPX options via a hash or a # block, and some additional options as well. def download(url, max_size: nil, progress_proc: nil, content_length_proc: nil, destination: nil, extension: nil, tempfile_name: nil, **options, &block) client = @client @@ -82,7 +82,7 @@ def download(url, max_size: nil, progress_proc: nil, content_length_proc: nil, d end # Starts retrieving the remote file and returns an IO-like object which - # downloads the response body on-demand. Accepts HTTP.rb options via a hash + # downloads the response body on-demand. Accepts HTTPX options via a hash # or a block. def open(url, rewindable: true, **options, &block) response = request(@client, url, stream: true, **options, &block) @@ -105,7 +105,15 @@ def open(url, rewindable: true, **options, &block) # Yields chunks of the response body to the block. def stream_body(response, &block) - response.each(&block) + response.each do |chunk| + next if (300..399).include?(response.status) + + block.call(chunk) + end + + if (300..399).include?(response.status) + raise Down::TooManyRedirects, "too many redirects" + end rescue => exception request_error!(exception) end @@ -113,7 +121,7 @@ def stream_body(response, &block) def request(client, url, method: @method, **options, &block) response = send_request(client, method, url, **options, &block) response.raise_for_status - response_error!(response) unless (200..299).include?(response.status) + response_error!(response) unless (200..399).include?(response.status) response rescue HTTPX::HTTPError response_error!(response) @@ -140,7 +148,6 @@ def response_error!(response) args = [response.status.to_s, response] case response.status - when 300..399 then raise Down::TooManyRedirects, "too many redirects" when 404 then raise Down::NotFound.new(*args) when 400..499 then raise Down::ClientError.new(*args) when 500..599 then raise Down::ServerError.new(*args)