Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

body_exists for requests without body should be False #4529

Merged
merged 1 commit into from
Jan 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/4528.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed request.body_exists returns wrong value for methods without body.
19 changes: 14 additions & 5 deletions aiohttp/_http_parser.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from __future__ import absolute_import, print_function
from cpython.mem cimport PyMem_Malloc, PyMem_Free
from libc.string cimport memcpy
from libc.limits cimport ULLONG_MAX
from cpython cimport (PyObject_GetBuffer, PyBuffer_Release, PyBUF_SIMPLE,
Py_buffer, PyBytes_AsString, PyBytes_AsStringAndSize)

Expand Down Expand Up @@ -270,6 +271,7 @@ cdef class HttpParser:
size_t _max_field_size
size_t _max_headers
bint _response_with_body
bint _read_until_eof

bint _started
object _url
Expand Down Expand Up @@ -309,7 +311,8 @@ cdef class HttpParser:
object protocol, object loop, object timer=None,
size_t max_line_size=8190, size_t max_headers=32768,
size_t max_field_size=8190, payload_exception=None,
bint response_with_body=True, bint auto_decompress=True):
bint response_with_body=True, bint read_until_eof=False,
bint auto_decompress=True):
cparser.http_parser_init(self._cparser, mode)
self._cparser.data = <void*>self
self._cparser.content_length = 0
Expand All @@ -334,6 +337,7 @@ cdef class HttpParser:
self._max_headers = max_headers
self._max_field_size = max_field_size
self._response_with_body = response_with_body
self._read_until_eof = read_until_eof
self._upgraded = False
self._auto_decompress = auto_decompress
self._content_encoding = None
Expand Down Expand Up @@ -427,8 +431,12 @@ cdef class HttpParser:
headers, raw_headers, should_close, encoding,
upgrade, chunked)

if (self._cparser.content_length > 0 or chunked or
self._cparser.method == 5): # CONNECT: 5
if (ULLONG_MAX > self._cparser.content_length > 0 or chunked or
hh-h marked this conversation as resolved.
Show resolved Hide resolved
self._cparser.method == 5 or # CONNECT: 5
(self._cparser.status_code >= 199 and
self._cparser.content_length == ULLONG_MAX and
self._read_until_eof)
):
payload = StreamReader(
self._protocol, timer=self._timer, loop=self._loop)
else:
Expand Down Expand Up @@ -545,7 +553,7 @@ cdef class HttpRequestParser(HttpParser):
bint response_with_body=True, bint read_until_eof=False):
self._init(cparser.HTTP_REQUEST, protocol, loop, timer,
max_line_size, max_headers, max_field_size,
payload_exception, response_with_body)
payload_exception, response_with_body, read_until_eof)

cdef object _on_status_complete(self):
cdef Py_buffer py_buf
Expand Down Expand Up @@ -573,7 +581,8 @@ cdef class HttpResponseParser(HttpParser):
bint auto_decompress=True):
self._init(cparser.HTTP_RESPONSE, protocol, loop, timer,
max_line_size, max_headers, max_field_size,
payload_exception, response_with_body, auto_decompress)
payload_exception, response_with_body, read_until_eof,
auto_decompress)

cdef object _on_status_complete(self):
if self._buf:
Expand Down
10 changes: 7 additions & 3 deletions tests/test_web_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,18 +685,22 @@ async def handler(request):
assert 200 == resp.status


async def test_empty_content_for_query_without_body(aiohttp_client) -> None:
@pytest.mark.parametrize("method", [
"get", "post", "options", "post", "put", "patch", "delete"
])
async def test_empty_content_for_query_without_body(
method, aiohttp_client) -> None:

async def handler(request):
assert not request.body_exists
assert not request.can_read_body
return web.Response()

app = web.Application()
app.router.add_post('/', handler)
app.router.add_route(method, '/', handler)
client = await aiohttp_client(app)

resp = await client.post('/')
resp = await client.request(method, '/')
assert 200 == resp.status


Expand Down