Skip to content

Commit

Permalink
Ensure body is consumed only once
Browse files Browse the repository at this point in the history
Fixes: kevin1024#846
Signed-off-by: Mathieu Parent <math.parent@gmail.com>
  • Loading branch information
sathieu committed Jul 2, 2024
1 parent 9cfa6c5 commit e0db062
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 1 deletion.
26 changes: 25 additions & 1 deletion tests/unit/test_stubs.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import contextlib
import http.client as httplib
from unittest import mock

from pytest import mark

from vcr import mode
from vcr import mode, use_cassette
from vcr.cassette import Cassette
from vcr.stubs import VCRHTTPSConnection

Expand All @@ -21,3 +22,26 @@ def testing_connect(*args):
vcr_connection.cassette = Cassette("test", record_mode=mode.ALL)
vcr_connection.real_connection.connect()
assert vcr_connection.real_connection.sock is not None

def test_body_consumed_once(self, tmpdir, httpbin):
testfile = str(tmpdir.join("body_consumed_once.yml"))
host, port = httpbin.host, httpbin.port
match_on = ["method", "uri", "body"]
chunks1 = [b"1234567890"]
chunks2 = [b"9876543210"]
with use_cassette(testfile, match_on=match_on):
conn1 = httplib.HTTPConnection(host, port)
conn1.request("POST", "/anything", body=iter(chunks1))
resp1 = conn1.getresponse()
assert resp1.status == 501 # Chunked request Not implemented
conn2 = httplib.HTTPConnection(host, port)
conn2.request("POST", "/anything", body=iter(chunks2))
resp2 = conn2.getresponse()
assert resp2.status == 501 # Chunked request Not implemented
with use_cassette(testfile, match_on=match_on) as cass:
conn2 = httplib.HTTPConnection(host, port)
conn2.request("POST", "/anything", body=iter(chunks2))
resp2 = conn2.getresponse()
assert resp2.status == 501 # Chunked request Not implemented
assert cass.play_counts[0] == 0
assert cass.play_counts[1] == 1
8 changes: 8 additions & 0 deletions vcr/stubs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,14 @@ def endheaders(self, message_body=None):

def getresponse(self, _=False, **kwargs):
"""Retrieve the response"""
# Some file-like objects or iterators can only be consumed once
if hasattr(self._vcr_request.body, "read"):
self._vcr_request.body = self._vcr_request.body.read()
elif hasattr(self._vcr_request.body, "__iter__") and not isinstance(
self._vcr_request.body,
(str, bytes, bytearray, list),
):
self._vcr_request.body = list(self._vcr_request.body)
# Check to see if the cassette has a response for this request. If so,
# then return it
if self.cassette.can_play_response_for(self._vcr_request):
Expand Down

0 comments on commit e0db062

Please sign in to comment.