Skip to content

Commit

Permalink
Explicitly store request data
Browse files Browse the repository at this point in the history
  • Loading branch information
a-gerhard committed Mar 18, 2024
1 parent 91a41bb commit 34f0756
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ junit-*.xml
build
dist
*.egg-info
/pytest_localserver/_version.py

# project files
.idea
Expand Down
8 changes: 7 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,13 @@ poking around in the code itself.
* ``content`` - content of next response (str, bytes, or iterable of either)
* ``headers`` - response headers (dict)
* ``chunked`` - whether to chunk-encode the response (enumeration)
* ``store_request_data`` - whether to store request data for later use

Once these attributes are set, all subsequent requests will be answered with
these values until they are changed or the server is stopped. A more
convenient way to change these is ::

httpserver.serve_content(content=None, code=200, headers=None, chunked=pytest_localserver.http.Chunked.NO)
httpserver.serve_content(content=None, code=200, headers=None, chunked=pytest_localserver.http.Chunked.NO, store_request_data=True)

The ``chunked`` attribute or parameter can be set to

Expand All @@ -108,6 +109,11 @@ poking around in the code itself.
If chunk encoding is applied, each str or bytes in ``content`` becomes one
chunk in the response.

You can use ``store_request_data=False`` to disable loading the request data into
memory. This will not make it possible to check the request data later in the request
object, but may make sense when posting a larger amount of data and you don't need
to check this.

The server address can be found in property

* ``url``
Expand Down
13 changes: 12 additions & 1 deletion pytest_localserver/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,18 @@ def __init__(self, host="127.0.0.1", port=0, ssl_context=None):
self.compress = None
self.requests = []
self.chunked = Chunked.NO
self.store_request_data = False

def __call__(self, environ, start_response):
"""
This is the WSGI application.
"""
request = Request(environ)

if self.store_request_data:
# need to invoke this method to cache the data
request.get_data(cache=True)

self.requests.append(request)
if (
request.content_type == "application/x-www-form-urlencoded"
Expand Down Expand Up @@ -129,7 +135,10 @@ def __call__(self, environ, start_response):

return response(environ, start_response)

def serve_content(self, content, code=200, headers=None, chunked=Chunked.NO):
def serve_content(
self, content, code=200, headers=None, chunked=Chunked.NO,
store_request_data=True
):
"""
Serves string content (with specified HTTP error code) as response to
all subsequent request.
Expand All @@ -138,6 +147,7 @@ def serve_content(self, content, code=200, headers=None, chunked=Chunked.NO):
:param code: HTTP status code
:param headers: HTTP headers to be returned
:param chunked: whether to apply chunked transfer encoding to the content
:param store_request_data: whether to store data sent as request payload.
"""
if not isinstance(content, (str, bytes, list, tuple)):
# If content is an iterable which is not known to be a string,
Expand All @@ -153,6 +163,7 @@ def serve_content(self, content, code=200, headers=None, chunked=Chunked.NO):
self.content = content
self.code = code
self.chunked = chunked
self.store_request_data = store_request_data
if headers:
self.headers = Headers(headers)

Expand Down
15 changes: 15 additions & 0 deletions tests/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ def test_HEAD_request(httpserver):
# assert resp.status_code == 200


def test_POST_request_data(httpserver):
headers = {"Content-type": "text/plain"}
httpserver.serve_content('TEST!', store_request_data=True)
requests.post(httpserver.url, data=b'testdata', headers=headers)
assert httpserver.requests[-1].data == b'testdata'


def test_POST_request_json(httpserver):
test_data = [{"test": "mock"}, 42]
headers = {"Content-type": "application/json"}
httpserver.serve_content('TEST!', store_request_data=True)
requests.post(httpserver.url, json=test_data, headers=headers)
assert httpserver.requests[-1].json == test_data


@pytest.mark.parametrize("chunked_flag", [http.Chunked.YES, http.Chunked.AUTO, http.Chunked.NO])
def test_chunked_attribute_without_header(httpserver, chunked_flag):
"""
Expand Down

0 comments on commit 34f0756

Please sign in to comment.