Nginx not enforcing default client_max_body_size ?

Maxim Dounin mdounin at mdounin.ru
Fri Dec 14 15:34:59 UTC 2018


Hello!

On Thu, Dec 13, 2018 at 09:16:12PM -0800, Dave Pedu wrote:

> Hello,
> 
> I came across some nginx behavior that seems odd to me. In my config, I 
> have this server block:
> 
> 
>      server {
>        server_name subdomain.somehostname.com
>        listen 443 ssl;
>        ssl_certificate     "/some/file.crt";
>        ssl_certificate_key "/some/other/file.key";
>        ssl_protocols       <redacted>
>        ssl_ciphers         <redacted>
>        return 307 https://anothersubdomain.somehostname.com$request_uri;
>      }
> 
> 
> I'm using a 307 redirect to cause clients to retry their original 
> request at the redirected destination, particularly for file uploads. 
> With the above configuration, client requests regardless of post size - 
> even larger than the default client_max_body_size - are redirected. For 
> example, a 6MB file upload:
> 
> 
>      $ curl -v --data-binary "@5mbRandomData.bin" 
> 'https://subdomain.somehostname.com/upload'
>      ...
>      > POST /upload HTTP/1.1
>      ...
>      > User-Agent: curl/7.54.0
>      > Content-Length: 6161400
>      > Content-Type: application/x-www-form-urlencoded
>      > Expect: 100-continue
>      >
>      < HTTP/1.1 100 Continue
>      < HTTP/1.1 307 Temporary Redirect
>      < Server: nginx/1.12.2
>      < Location: https://anothersubdomain.somehostname.com/upload
>      ...
> 
> 
> However, when I place the "return" line within a location block as shown 
> here:
> 
> 
>      server {
>        server_name subdomain.somehostname.com
>        listen 443 ssl;
>        ssl_certificate     "/some/file.crt";
>        ssl_certificate_key "/some/other/file.key";
>        ssl_protocols       <redacted>
>        ssl_ciphers         <redacted>
>        location / {
>            return 307 
> https://anothersubdomain.somehostname.com$request_uri;
>        }
>      }
> 
> 
> ...then clients posting larger than the default client_max_body_size are 
> sent an error instead. Again, with a 6MB upload:
> 
> 
>      $ curl -v --data-binary "@5mbRandomData.bin" 
> 'https://subdomain.somehostname.com/upload'
>      > POST /upload HTTP/1.1
>      ...
>      > User-Agent: curl/7.54.0
>      > Content-Length: 6161400
>      > Content-Type: application/x-www-form-urlencoded
>      > Expect: 100-continue
>      >
>      < HTTP/1.1 413 Request Entity Too Large
>      < Server: nginx/1.12.2
> 
> 
> Which seems like correct behavior in contrast to the first example since 
> client_max_body_size must be set to 0 to allow unlimited sized uploads, 
> and the default value is 1m. I didn't see anything in the documentation 
> about selective application of the body size limit. Is this a bug?

The client_max_body_size limit is only enforced when nginx selects 
a location (or when reading the body if Content-Length is not 
known in advance).  This is because different limits can be 
configured in different locations, so a configuration like 

    location / {
        client_max_body_size 1m;
        ...
    }

    location = /upload.cgi {
        client_max_body_size 100m;
        ...
    }

will properly allow uploading of large files via "/upload.cgi", 
but will restrict maximum request body size on other requests.

As such, client_max_body_size is only enforced when nginx chooses 
some location configuration to work with.  And in your first 
configuration the request is answered during processing server 
rewrites, before nginx has a chance to select a location.

This is not really important though, since nginx does not try 
read a request body in such a case.  Rather, it will discard 
anything - much like it will do when returning an error anyway.

-- 
Maxim Dounin
http://mdounin.ru/


More information about the nginx mailing list