abersheeran/a2wsgi

Connexion 3 issue with FlaskApp and WSGIResponder.wsgi

Lewiscowles1986 opened this issue · 4 comments

.venv/lib/python3.11/site-packages/a2wsgi/wsgi.py

    def wsgi(self, environ: Environ, start_response: StartResponse) -> None:
        iterable = self.app(environ, start_response)
        try:
            for chunk in iterable:
                self.send(
                    {"type": "http.response.body", "body": chunk, "more_body": True}
                )

            self.send({"type": "http.response.body", "body": b""})
        finally:
            getattr(iterable, "close", lambda: None)()

Always leads to AWS returning "" as the body.

I'm fairly certain it's this piece of code as body is a Bytes object

chunk = b"Hello lewis"

version affected 1.10.4 (ships as transitive dependency via Connexion 3)

Can you provide a method for reproduction?

test-api-68d50d1e-db07-4e24-952a-437efdc51d53.zip

This is what I've uploaded to AWS Lambda

It's pretty-much the connexion 3 tutorial

And here is the "fixed" version without that line
Archive 2.zip

It returns me a base64 encoded response; which works with API Gateway

The only other thing I can think of is that asgi_aws code is at fault

.venv/lib/python3.11/site-packages/asgi_aws/services/aws.py:

    async def receive(self) -> Message:
        event = self.request["event"]
        body = event.get("body", "")
        if body is None:
            body = b""
        elif event.get("isBase64Encoded", False):
            body = b64decode(body)
        else:
            body = body.encode()
        return {
            "type": "http.request",
            "body": body,
            "more_body": False,
        }

    @property
    def response(self) -> Response:
        event = self.request["event"]
        if "version" in event:
            is_base64_encoded = True
            body = b64encode(self.body).decode()
        else:
            is_base64_encoded = False
            try:
                body = self.body.decode()
            except UnicodeDecodeError:
                is_base64_encoded = True
                body = b64encode(self.body).decode()
        return {
            "statusCode": self.status_code,
            "headers": dict(self.headers),
            "body": body,
            "isBase64Encoded": is_base64_encoded,
        }

Closing as this is actually an issue with asgi-aws and it's naive implementation. The hack should hold for Flask apps, but not any true ASGI.

Solved using https://github.com/jordaneremieff/mangum, which "just-works" ™️ and should work with any True ASGI app, due to a more robust way of handling