Skip to content

Commit

Permalink
Fix FrozenError in Typhoeus streaming response body
Browse files Browse the repository at this point in the history
When stubbing a response for the Typhoeus adapter, and the Typhoeus
request has an `on_body` callback, a `FrozenError` exception is raised
when attempting to concatenate the current chunk of the response to
the existing response body (i.e. `response.body << chunk`).

FWIW, my use case for this is to abort a request as early as possible
when the response body exceeds a given size, specifically when the
response doesn't have a `Content-Length` header.

The example below illustrates the issue:

```ruby
require "bundler/inline"

gemfile do
  source "https://rubygems.org"

  gem "typhoeus", "1.4.1"
  gem "webmock", "3.24.0"
end

WebMock.enable!
WebMock.stub_request(:get, "https://example.com").to_return(status: "200", body: "body")

request = Typhoeus::Request.new("https://example.com")

request.on_body do |chunk, response|
  response.body << chunk
end

request.run
```

This change initializes the Typhoeus response body to a non-frozen,
mutable string when using the `on_body` callback.
  • Loading branch information
patrickjaberg committed Nov 6, 2024
1 parent 9ff63ac commit 6b8951a
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def self.request_hash(request_signature)
request.execute_headers_callbacks(response)
end
if request.respond_to?(:streaming?) && request.streaming?
response.options[:response_body] = ""
response.options[:response_body] = String.new
request.on_body.each { |callback| callback.call(webmock_response.body, response) }
end
request.finish(response)
Expand Down
13 changes: 13 additions & 0 deletions spec/acceptance/typhoeus/typhoeus_hydra_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,19 @@
expect(test_complete).to eq("")
end

it "should initialize the streaming response body with a mutible (non-frozen) string" do
skip("This test requires a newer version of Typhoeus") unless @request.respond_to?(:on_body)

stub_request(:any, "example.com").to_return(body: "body")

@request.on_body do |body_chunk, response|
response.body << body_chunk
end
hydra.queue @request

expect{ hydra.run }.not_to raise_error
end

it "should call on_headers with 2xx response" do
body = "on_headers fired"
stub_request(:any, "example.com").to_return(body: body, headers: {'X-Test' => '1'})
Expand Down

0 comments on commit 6b8951a

Please # to comment.