Forums

504 Timeout On Flask Route (playwright + chromium)

Hi all

One of my flask route is returning 504 error out of nowhere, it was working perfectly last month.

I tried sending POST request through javascript and postman and both returns the same error.

What boggles my mind is I get a proper 200 response by running this route locally. Only difference is on my local machine I use local chromium:

browser = await p.chromium.launch()

And for Pythonanywhere:

browser = await p.chromium.launch(
    executable_path="/usr/bin/chromium",
    args=["--disable-gpu", "--headless"]
)

I added bunch of print statements throughout the code, and go an idea where it stops before timeout:

async def generate_pdf(html_content):
    async with async_playwright() as p:    
        browser = await p.chromium.launch(
            executable_path="/usr/bin/chromium",
            args=["--disable-gpu", "--headless"]
        )
        page = await browser.new_page()
        await page.set_content(html_content, wait_until='networkidle')
        pdf_options = {
            'width': '4in',
            'height': '6in',
            'margin': {
                'right': '0.1in',
                'bottom': '0.1in',
                'left': '0.1in'
            },
            'print_background': True
        }
        print("log8")
        try:
            pdf = await page.pdf(**pdf_options)
        except Exception as e:
            print(f"Error generating PDF: {e}")
            return Response("Error generating PDF", status=500)
        await browser.close()

That log8 is the last statement I see before timeout.

Any help would be much appreciated.

async and await will not work in a web app. Try rewriting your code so that it does not rely on those. You can also move the parts of you code that require async and await out of the web app: https://help.pythonanywhere.com/pages/AsyncInWebApps/

Thanks Glenn, but that doesn't fix the timeout issue.

I've pinpointed the issue to this line:

pdf = page.pdf(**pdf_options)

I tried setting the content of pdf to just a string of text, and now it works perfectly, but rendering my intended content to the pdf is taking too long.

As I mentioned previously this worked last month in development (we were on the same plan back then as now) and it only took couple seconds back then. I haven't touched this route ever since and now we're in final testing stage we can't launch due to this issue.

Any way you could help?

Just to confirm that we understand the issue correctly -- are you saying your async code was actually working in a Flask app? Also, do you see any relevant entries in your web app logs (server / error)?

Hi Pafk,

Previously the async was actually working in a Flask webapp, but I don't think that was the problem.

I think I should explain the route in a bit more detail:

The route takes a JSON payload from a POST request, then use that payload to build an html page. Then using Playwright I render that page into pdf, before finally returning the pdf as response. This pdf part is important because I need it in specific size, i.e. I can't return the html as is because the paper size won't be right. I know this is a roundabout way of doing this and I could simply use weasyprint (I'm aware it's included here), but some css styles aren't available in weasyprint.

On development I managed to get the route work, but this week when I touched on it again the script timeouts exactly in the pdf rendering part (refer to my previous comment). So I tried feeding it a simple page with just a <div>test</div> to render as pdf and it works.

So if the original html page I'm trying to render into pdf is too heavy, I don't understand why it worked last month on development and not now.

Nothing in error log, below is the server log that might relate to the timeout:

2024-10-29 00:29:48 log1
2024-10-29 00:29:48 log2
2024-10-29 00:29:48 log3
2024-10-29 00:29:48 log4
2024-10-29 00:29:49 log5
2024-10-29 00:29:49 log6
2024-10-29 00:29:49 log7
2024-10-29 00:29:49 log8
2024-10-29 00:29:49 log8a
2024-10-29 00:32:41 Tue Oct 29 00:32:41 2024 - received message 0 from emperor
2024-10-29 00:32:41 SIGINT/SIGTERM received...killing workers...
2024-10-29 00:32:42 worker 1 buried after 1 seconds
2024-10-29 00:32:42 worker 2 buried after 1 seconds
2024-10-29 00:32:42 goodbye to uWSGI.

The code it ran on looked like this:

 print("log8")
    try:
        print("log8a")
        pdf = page.pdf(**pdf_options)
        print("log8b")

Yes, it looks like it just takes too much time. Maybe consider something like https://help.pythonanywhere.com/pages/AsyncInWebApps/#the-async-solution-a-task-queue