Opened 4 weeks ago

Closed 4 weeks ago

Last modified 3 weeks ago

#1971 closed defect (invalid)

Invalid 200 (OK) response code to range request

Reported by: topoden@… Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.19.x
Keywords: ranged request Cc:
uname -a: Linux 4.4.0-70-generic #91~14.04.1-Ubuntu SMP Wed Mar 22 15:48:21 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.14.0
built by gcc 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.4)
built with OpenSSL 1.0.1f 6 Jan 2014
TLS SNI support enabled

Description

Observed behaviour: nginx responds with 200 (OK) to 0-10 ranged request for empty file.

Relevant part of nginx configuration file:

server {
   listen localhost:9998 backlog=65536 deferred reuseport;
   autoindex  on;
   root       ~/nginx_tests/files;
    
   location / {
   }
   }

Steps to reproduce:

 ~/nginx_tests$ touch files/empty.txt
 ~/nginx_tests$ curl http://localhost:9998/empty.txt -i -H "Range: bytes=0-10" 

HTTP/1.1 200 OK
Server: nginx/1.14.0
Date: Thu, 07 May 2020 08:00:22 GMT
Content-Type: text/plain
Content-Length: 0
Last-Modified: Thu, 07 May 2020 08:00:07 GMT
Connection: keep-alive
ETag: "5eb3c007-0"
Accept-Ranges: bytes

Expected behaviour: According to https://tools.ietf.org/html/rfc7233#section-2.1, nginx was expected to return 416 (Range Not Satisfiable):

If a valid byte-range-set includes at least one byte-range-spec with a first-byte-pos that is less than the current length of the representation, or at least one suffix-byte-range-spec with a non-zero suffix-length, then the byte-range-set is satisfiable.
**Otherwise, the byte-range-set is unsatisfiable.**

Possibly related nginx source code:
Because the code adjusts parsed end value with content size here: https://trac.nginx.org/nginx/browser/nginx/src/http/modules/ngx_http_range_filter_module.c#L363

It mistakenly decides that parsed range is invalid and returns NGX_DECLINED here: https://trac.nginx.org/nginx/browser/nginx/src/http/modules/ngx_http_range_filter_module.c#L391

The code then handles valid ranged request as invalid here: https://trac.nginx.org/nginx/browser/nginx/src/http/modules/ngx_http_range_filter_module.c#L249


Change History (3)

comment:1 by Maxim Dounin, 4 weeks ago

Resolution: invalid
Status: newclosed

As per RFC 7233, Section 3.1, "A server MAY ignore the Range header field". This is what nginx does when a range requested from an empty file. That is, the behaviour is perfectly valid as per HTTP specification.

For reasons why nginx behaves this way please see changeset aeaac3ccee4f and ticket #1031. In short, this is perfectly valid behaviour and simplifies at least some cases, as seen with the slice module.

comment:2 by topoden@…, 3 weeks ago

Frankly, this is a weird approach to use "...may ignore..." clause only in subset of valid requests. Its clear that the request is valid. It also is clear that the valid request can not be satisfied. Why returning 200? Because it simplifies some cases? Well it complicates some cases too, otherwise I would not report this... :)

comment:3 by Maxim Dounin, 3 weeks ago

Any valid client is expected to handle 200 anyway, as servers are not required to support range requests, so returning 200 for empty files is expected to simplify more cases than it complicates.

Note well that nginx may (and will) return 200 in various other cases, such as when more than max_ranges ranges are requested, or total length of requested ranges is larger than the length of the file. Not to mention non-static resources, where range support is usually not available at all.

Note: See TracTickets for help on using tickets.