Nginx 413 error does not get to the browser

httpnginxruby-on-railsupload

I think my situation is very similar to Why might a 413 not be flushed to the client immediately? , what is indented is where my situation is different

I have my local development server returning status 413 for oversized file uploads and the client is receiving these immediately – as I require. Both my error and access log show this, but it takes around 6 seconds, so I wonder if my browser is waiting to send the image? and then receive it the 413 error?

My remote server is the same version of Nginx and more-or-less the same configuration, but the 413 never reaches the browser.

An error indicating the data is oversized appears in the error log straight away and nothing appears in the access log. The browser continues to send the data and after 30 seconds the 413 status appears in the access log (and again in the error log) and the browser times out with an internal 'connection reset' error. Here is where my situation is different from this problem. I still get the (client intended to send too large body:) in error.log and (POST /path/to/my/imageupload HTTP/1.1 413) in access.log right away, but I also get a respond with no Status (in Chrome the status is failed or 0) right away

When I curl the same request I do get the 413 error respond. Which matches mgorven responded in that post.

I see mgorven said that the browser waits to send everything before receiving anything from server.
Is that why it doesn't accept the 413? Any idea how to fix it? If i set keepalive_requests to 0 would it break anything? like uploading big images (smaller than 5mb)?
So how do people handle nginx 413 errors without showing the nginx 413 error page?

Also along the same topic, the above happens when I try to upload through javascript. Part of my app has a Rails uploader, and when it uploads a large file, it just drops the connection. But my local box shows the nginx 413 error page. Any ideas how to get around this and just send a Json respond?

Best Answer

Setting keepalive_requests to 0 won't break anything, but it will disable persistent connections (which may result in a reduction in performance).

You can configure nginx to send a JSON response, but note that you'll still need the client to behave correctly and check for a response before finishing sending the request body.

/var/www/errors/413.json:

{"message": "Request Entity Too Large"}

/etc/nginx.conf:

location /errors {
    types {
        application/json    json;
        text/html   html;
        text/html   htm;
    }
}

error_page 413 /errors/413.json;