Nginx not enforcing default client_max_body_size ?

Dave Pedu nginx-ml at davepedu.com
Fri Dec 14 17:24:04 UTC 2018


Hello,


On 2018-12-14 07:34, Maxim Dounin wrote:
> 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.


That makes sense - I appreciate your reply, Maxim. Is there an area of 
the documentation that describes this selective enforcement when a 
location block is not selected? I would like to determine what other 
options are handled similarly.

Looking at the description of client_max_body_size here [1], the 
language is quite clear that the setting's value is compared to 
Content-Length, a header that's present in both situations above, hence 
my confusion.

Thanks!
Dave

[1] 
http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size





More information about the nginx mailing list