From 874278d23edef467c6470c3dfb3a1fa759383b1a Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Tue, 19 Mar 2024 14:55:53 +1100 Subject: [PATCH 1/2] FEATURE: implement body streaming for Net::HTTP Per #629, this adds support for body stream mocking. It is only implemented on Net::HTTP for now as this is the most surgical change we can make without impacting the entire framework. --- CHANGELOG.md | 4 ++++ README.md | 18 ++++++++++++++++++ .../http_lib_adapters/net_http_response.rb | 6 +++++- spec/acceptance/net_http/net_http_spec.rb | 15 +++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8e7c6ce..867d6e13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +# 3.13.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("/") From b6775cf22f693cb7166a113b34e36a8f6c0b0482 Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Wed, 20 Mar 2024 09:34:17 +1100 Subject: [PATCH 2/2] Fix future release version number --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 867d6e13..382328a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -# 3.13.1 (future) +# 3.23.1 (future) * Add support for streaming responses in Net::HTTP adapter