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

question: If my API already has a base64-encoded PNG, how ought it return it? #283

Open
jrobbins-LiveData opened this issue Dec 2, 2022 · 3 comments

Comments

@jrobbins-LiveData
Copy link
Sponsor

One API endpoint I have receives a base64-encoded PNG. Can I return the data via mangum with content-type image/png without having to first base64-decode it?

@jordaneremieff
Copy link
Owner

@jrobbins-LiveData I can provide some general information, but would need more details to say much more. The decoding is done by the maybe_encode_body function based on the value of isBase64Encoded from the event for a handler like this. If I'm not misunderstanding, then sounds like you may want to use a custom handler subclass to override this, but just taking my best guess atm.

@jrobbins-LiveData
Copy link
Sponsor Author

Here's a more concrete version of my question.

First, here's where the base64 feature works perfectly. Using pypdf, for example, I can merge some PDF files, in memory, and simply return a FastAPI Response of the bytes, and the ALB adapter of Mangum does exactly what I want.

    # some FastAPI route that receives a JSON body giving instructions about what PDF files to merge
    ...
    output_io = io.BytesIO()
    merger = PdfMerger()
    for pdf_io in pdf_ios:
        merger.append(pdf_io)
    merger.write(output_io)
    merger.close()
    return Response(output_io.getvalue(), media_type='application/pdf')

In a different route, I need to return a screenshot from a Selenium embedded browser using this api. If I get the screenshot as bytes, then the code is equivalent to the PDF example:

    ...
    browser.get(url)
    screenshot = browser.get_screenshot_as_png()
    return Response(content=screenshot, media_type='image/png')

But, suppose for performance reasons, I need to call get_screenshot_as_base64 instead of get_screenshot_as_png?

    ...
    browser.get(url)
    screenshot = browser.get_screenshot_as_base64()
    # NOTE this currently does not work because `maybe_encode_body` base64-encodes the already encoded string
    return Response(content=screenshot, media_type='image/png')

The ALB body @Property uses the incoming request event as its flag, but, since a REST API taking JSON as its input might need to return a base64-encoded response, it would be nice to somehow be able to flag this without reference to the incoming event.

    @property
    def body(self) -> bytes:
        return maybe_encode_body(
            self.event.get("body", b""),
            is_base64=self.event.get("isBase64Encoded", False),
        )

How would I use the handler subclass technique you referred to in order to solve this?

@pkit
Copy link

pkit commented Nov 2, 2023

It's impossible to handle right now, as Response expects bytes and is irreversibly mangled by handle_base64_response_body function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants