Do now swallow response body on persistent connection (#32729)
This commit is contained in:
		
							parent
							
								
									4e2c15b45d
								
							
						
					
					
						commit
						8e2c642d44
					
				| @ -111,16 +111,10 @@ class Request | ||||
|     end | ||||
| 
 | ||||
|     begin | ||||
|       # If we are using a persistent connection, we have to | ||||
|       # read every response to be able to move forward at all. | ||||
|       # However, simply calling #to_s or #flush may not be safe, | ||||
|       # as the response body, if malicious, could be too big | ||||
|       # for our memory. So we use the #body_with_limit method | ||||
|       response.body_with_limit if http_client.persistent? | ||||
| 
 | ||||
|       yield response if block_given? | ||||
|     ensure | ||||
|       http_client.close unless http_client.persistent? | ||||
|       response.truncated_body if http_client.persistent? && !response.connection.finished_request? | ||||
|       http_client.close unless http_client.persistent? && response.connection.finished_request? | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | ||||
| @ -4,7 +4,9 @@ require 'rails_helper' | ||||
| require 'securerandom' | ||||
| 
 | ||||
| RSpec.describe Request do | ||||
|   subject { described_class.new(:get, 'http://example.com') } | ||||
|   subject { described_class.new(:get, 'http://example.com', **options) } | ||||
| 
 | ||||
|   let(:options) { {} } | ||||
| 
 | ||||
|   describe '#headers' do | ||||
|     it 'returns user agent' do | ||||
| @ -39,8 +41,8 @@ RSpec.describe Request do | ||||
|   end | ||||
| 
 | ||||
|   describe '#perform' do | ||||
|     context 'with valid host' do | ||||
|       before { stub_request(:get, 'http://example.com') } | ||||
|     context 'with valid host and non-persistent connection' do | ||||
|       before { stub_request(:get, 'http://example.com').to_return(body: 'lorem ipsum') } | ||||
| 
 | ||||
|       it 'executes a HTTP request' do | ||||
|         expect { |block| subject.perform(&block) }.to yield_control | ||||
| @ -71,9 +73,9 @@ RSpec.describe Request do | ||||
|         expect(subject.send(:http_client)).to have_received(:close) | ||||
|       end | ||||
| 
 | ||||
|       it 'returns response which implements body_with_limit' do | ||||
|       it 'yields response' do | ||||
|         subject.perform do |response| | ||||
|           expect(response).to respond_to :body_with_limit | ||||
|           expect(response.body_with_limit).to eq 'lorem ipsum' | ||||
|         end | ||||
|       end | ||||
|     end | ||||
| @ -95,6 +97,43 @@ RSpec.describe Request do | ||||
|         expect { subject.perform }.to raise_error Mastodon::ValidationError | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'with persistent connection' do | ||||
|       before { stub_request(:get, 'http://example.com').to_return(body: SecureRandom.random_bytes(2.megabytes)) } | ||||
| 
 | ||||
|       let(:http_client) { described_class.http_client.persistent('http://example.com') } | ||||
|       let(:options) { { http_client: http_client } } | ||||
| 
 | ||||
|       it 'leaves connection open after completely consumed response' do | ||||
|         allow(http_client).to receive(:close) | ||||
| 
 | ||||
|         subject.perform { |response| response.truncated_body(3.megabytes) } | ||||
| 
 | ||||
|         expect(http_client).to_not have_received(:close) | ||||
|       end | ||||
| 
 | ||||
|       it 'leaves connection open after nearly consumed response' do | ||||
|         allow(http_client).to receive(:close) | ||||
| 
 | ||||
|         subject.perform { |response| response.truncated_body(1.8.megabytes) } | ||||
| 
 | ||||
|         expect(http_client).to_not have_received(:close) | ||||
|       end | ||||
| 
 | ||||
|       it 'closes connection after unconsumed response' do | ||||
|         allow(http_client).to receive(:close) | ||||
| 
 | ||||
|         subject.perform | ||||
| 
 | ||||
|         expect(http_client).to have_received(:close) | ||||
|       end | ||||
| 
 | ||||
|       it 'yields response' do | ||||
|         subject.perform do |response| | ||||
|           expect(response.body_with_limit(2.megabytes).size).to eq 2.megabytes | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe "response's body_with_limit method" do | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user