Nginx May Cut You Off Early

How the default configuration bit me.

I very recently launched, a crowd-funding website for a short film I am working on. As a donator, you are able to upload an avatar to be presented with your credit. I had limited the file size to 2MB... or so I had thought.

Underneath, the site is built with Flask, served with Gunicorn, and behind an Nginx reverse proxy.

Unfortunately, I received reports that some uploads were failing and reported as "Error: undefined" to the user. Strangely, it didn't seem to be an error in the Python app, as I was not receiving any tracebacks when this error occurred.

It turns out that Nginx has some default configuration that I wasn't expecting.

The key is the client_max_body_size setting, which limits the body size that Nginx will process (or pass on to a proxy). The default setting is 1MB.

Ergo, while I had correctly set both JavaScript and Python to allow for 2MB uploads, Nginx would still cut you off early. The JavaScript would happily allow you to upload a 1.5MB file, but fail when Nginx decided it was too large.

If your browser sends the size of the upload in the headers, Nginx would cut it off immediately (as seen on iOS). Otherwise, the user would watch as the upload made progress, only to be cut off when Nginx eventually returned a 413.

Fortunately, the only people to experience the problem either worked around it, or powered through the donation process anyways. So I offer a huge thanks to Madeleine, Marcin, and You-Know-Who for contributing nonetheless!

Posted . Categories: .