diff --git a/CHANGELOG.md b/CHANGELOG.md index b8e7c6ce..382328a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# 3.23.1 (future) + + * Add support for streaming responses in Net::HTTP adapter + # 3.23.0 * Fixed HTTP.rb adapter to support streaming real responses when WebMock is enabled. diff --git a/README.md b/README.md index 5461101e..469ef9c7 100644 --- a/README.md +++ b/README.md @@ -453,6 +453,24 @@ stub_request(:any, 'www.example.net').to_timeout RestClient.post('www.example.net', 'abc') # ===> RestClient::RequestTimeout ``` +### Streaming response + +Net::HTTP supports streaming responses. WebMock can simulate this by specifying an Array for body. +This is only implemented for Net::HTTP at the moment. + +```ruby +stub_http_request(:get, "www.example.com").to_return(body: ["a", "b", "c"]) + +Net::HTTP.start('www.example.com') do |http| + req = Net::HTTP::Get.new('/') + http.request(req) do |res| + res.read_body do |segment| + puts segment + end + end +end # ===> "a\nb\nc\n" +``` + ### Multiple responses for repeated requests ```ruby diff --git a/lib/webmock/http_lib_adapters/net_http_response.rb b/lib/webmock/http_lib_adapters/net_http_response.rb index c9139a7a..967e4fde 100644 --- a/lib/webmock/http_lib_adapters/net_http_response.rb +++ b/lib/webmock/http_lib_adapters/net_http_response.rb @@ -25,7 +25,11 @@ def read_body(dest = nil, &block) return nil if @body.nil? dest ||= ::Net::ReadAdapter.new(block) - dest << @body.dup + if @body.is_a?(Array) + @body.each { |part| dest << part.dup } + else + dest << @body.dup + end @body = dest ensure # allow subsequent calls to #read_body to proceed as normal, without our hack... diff --git a/spec/acceptance/net_http/net_http_spec.rb b/spec/acceptance/net_http/net_http_spec.rb index ad921f5a..55fe7036 100644 --- a/spec/acceptance/net_http/net_http_spec.rb +++ b/spec/acceptance/net_http/net_http_spec.rb @@ -142,6 +142,21 @@ class TestMarshalingInWebMockNetHTTP expect(response_body).to eq("abc") end + it "should support streaming a response body", focus: true do + stub_http_request(:get, "www.example.com").to_return(body: ["a", "b", "c"]) + response_body = +"" + + http_request(:get, "http://www.example.com/") do |response| + i = 0 + response.read_body do |fragment| + response_body << "#{fragment}#{i}" + i += 1 + end + end + + expect(response_body).to eq("a0b1c2") + end + it "should handle Net::HTTP::Post#body" do stub_http_request(:post, "www.example.com").with(body: "my_params").to_return(body: "abc") req = Net::HTTP::Post.new("/")