Skip to content

Commit d6be0ce

Browse files
committed
Requests chunk encoded request handling
1 parent 4658b25 commit d6be0ce

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

openapi_core/contrib/requests/requests.py

+13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""OpenAPI core contrib requests requests module"""
2+
from typing import Mapping
23
from typing import Optional
34
from typing import Union
45
from urllib.parse import parse_qs
@@ -7,6 +8,7 @@
78
from requests import PreparedRequest
89
from requests import Request
910
from requests.cookies import RequestsCookieJar
11+
from requests.utils import rewind_body
1012
from werkzeug.datastructures import Headers
1113
from werkzeug.datastructures import ImmutableMultiDict
1214

@@ -67,6 +69,17 @@ def method(self) -> str:
6769
def body(self) -> Optional[str]:
6870
if self.request.body is None:
6971
return None
72+
is_stream = all(
73+
[
74+
hasattr(self.request.body, "__iter__"),
75+
not isinstance(self.request.body, (str, list, tuple, Mapping)),
76+
]
77+
)
78+
if is_stream:
79+
chunks = list(self.request.body)
80+
body = "".join(chunks)
81+
self.request.body = (x for x in chunks)
82+
return body
7083
if isinstance(self.request.body, bytes):
7184
return self.request.body.decode("utf-8")
7285
assert isinstance(self.request.body, str)

tests/integration/contrib/requests/test_requests_validation.py

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from types import GeneratorType
2+
13
import pytest
24
import requests
35
import responses
@@ -72,6 +74,22 @@ def test_request_validator_path_pattern(self, request_unmarshaller):
7274
result = request_unmarshaller.unmarshal(openapi_request)
7375
assert not result.errors
7476

77+
def test_request_validator_encoded_chunks(self, request_unmarshaller):
78+
def gen():
79+
yield '{"param1": 1}'
80+
81+
request = requests.Request(
82+
"POST",
83+
"http://localhost/browse/12/",
84+
params={"q": "string"},
85+
headers={"content-type": "application/json"},
86+
data=gen(),
87+
)
88+
openapi_request = RequestsOpenAPIRequest(request)
89+
result = request_unmarshaller.unmarshal(openapi_request)
90+
assert not result.errors
91+
assert request.data is GeneratorType
92+
7593
def test_request_validator_prepared_request(self, request_unmarshaller):
7694
request = requests.Request(
7795
"POST",

0 commit comments

Comments
 (0)