Skip to content

Bug - handler.body returns a str resulting in TypeError: a bytes-like object is required, not 'str' #181

@nathanglover

Description

@nathanglover

First this bug was introduced post 0.11.0 when the handlers were refactored.

Traceback

Exception in 'http' protocol.
--
Traceback (most recent call last):
File "/function/src/mangum/mangum/protocols/http.py", line 81, in run
await app(self.request.scope, self.receive, self.send)
File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/asgi.py", line 149, in __call__
body_file = await self.read_body(receive)
File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/asgi.py", line 181, in read_body
body_file.write(message['body'])
File "/usr/lib/python3.8/tempfile.py", line 896, in write
rv = file.write(s)
TypeError: a bytes-like object is required, not 'str'

I was able to trace the issue down to the def body() method in the handler classes. Adding assert type(handler.body) == bytes to the _basic tests will reveal the error.

        handler = AwsAlb(example_event, example_context)
>       assert type(handler.body) == bytes
E       AssertionError: assert <class 'str'> == <class 'bytes'>
E         +<class 'str'>
E         -<class 'bytes'>

In 0.11.0 the body was guaranteed to be bytes because of the following snippet:

is_binary = event.get("isBase64Encoded", False)
initial_body = event.get("body") or b""
if is_binary:
    initial_body = base64.b64decode(initial_body)
elif not isinstance(initial_body, bytes):  # forces strings to be bytes.
     initial_body = initial_body.encode()

For most handlers the refactored code looks like this:

@property
def body(self) -> bytes:
    body = self.trigger_event.get("body", b"")
    if self.trigger_event.get("isBase64Encoded", False):
        body = base64.b64decode(body)
    return body

If self.trigger_event has a body key than the body returned will be whatever the type of the value is, which might not be bytes.

The solution I believe is to add the code from 0.11.0 to the body function.:

if not isinstance(body, bytes):
    body = body.encode()

I'll work on updating the tests and putting a PR with the fix if the above seems correct.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions