if-range issue

Anatoli Marinov a.marinov at ucdn.com
Wed Aug 13 11:08:10 UTC 2014


I know this, but I used nginx as a reverse proxy and Etag comes from remote
server through nginx upstream. In general I do not have any control on its
value. Nginx uses this value as it is sent from the other server. The file
is cached with it and also this value is send to all http clients.


On Wed, Aug 13, 2014 at 1:22 PM, Roman Arutyunyan <arut at nginx.com> wrote:

> Hello,
>
> Etag value must be a quoted string.  Please add double quotes to
> ETag and If-Range arguments and try again.
>
> RFC7232 / Section 2.3
>
>      ETag       = entity-tag
>
>      entity-tag = [ weak ] opaque-tag
>      weak       = %x57.2F ; "W/", case-sensitive
>      opaque-tag = DQUOTE *etagc DQUOTE
>      etagc      = %x21 / %x23-7E / obs-text
>                 ; VCHAR except double quotes, plus obs-text
>
> On 13 Aug 2014, at 13:24, Anatoli Marinov <a.marinov at ucdn.com> wrote:
>
> > Hello colleagues,
> > Yesterday I found an issue with latest chrome and nginx 1.6.0.
> > For the following request nginx returns 200 OK instead of 206 partial
> response:
> >
> > REQUEST
> > GET /test.mp4 HTTP/1.1
> > Range: bytes=53037809-53037867
> > User-Agent: curl/7.33.0
> > Host: mydomain.com
> > Accept: */*
> > If-Range: 99f71760accc95bbdeadece7a87f507a
> >
> > RESPONSE
> > HTTP/1.1 200 OK
> > Server: nginx
> > Date: Wed, 13 Aug 2014 09:09:18 GMT
> > Content-Type: video/mp4
> > Content-Length: 53037868
> > Connection: keep-alive
> > Keep-Alive: timeout=150
> > Last-Modified: Fri, 30 May 2014 00:54:47 GMT
> > Etag: 99f71760accc95bbdeadece7a87f507a
> > Expires: Fri, 15 Aug 2014 15:22:31 GMT
> > Cache-Control: max-age=360000
> > Accept-Ranges: bytes
> >
> > For this request nginx should return partial response with just a few
> bytes (58).
> > In general Etag and If-Range are equal and there and the range request
> should be satisfied.
> > I thing in the file ngx_http_range_filter_module.c there is wrong
> comparation.
> >
> > This check:
> >     if (r->headers_in.if_range) {
> >
> >         if_range = &r->headers_in.if_range->value;
> >
> >         if (if_range->len >= 2 && if_range->data[if_range->len - 1] ==
> '"') {
> >
> >             if (r->headers_out.etag == NULL) {
> >                 goto next_filter;
> >             }
> >
> >             etag = &r->headers_out.etag->value;
> >
> >             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
> >                            "http ir:%V etag:%V", if_range, etag);
> >
> >             if (if_range->len != etag->len
> >                 || ngx_strncmp(if_range->data, etag->data, etag->len) !=
> 0)
> >             {
> >                 goto next_filter;
> >             }
> >
> >             goto parse;
> >         }
> >
> >         if (r->headers_out.last_modified_time == (time_t) -1) {
> >             goto next_filter;
> >         }
> >
> >         if_range_time = ngx_http_parse_time(if_range->data,
> if_range->len);
> >
> >         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
> >                        "http ir:%d lm:%d",
> >                        if_range_time, r->headers_out.last_modified_time);
> >
> >         if (if_range_time != r->headers_out.last_modified_time) {
> >             goto next_filter;
> >         }
> >     }
> >
> >
> >
> >
> ------------------------------------------------------------------------------------------------------------------------
> >
> >
> >
> > Should be replaced with this:
> >     if (r->headers_in.if_range) {
> >
> >         if_range = &r->headers_in.if_range->value;
> >
> >         if (r->headers_out.etag) {
> >             etag = &r->headers_out.etag->value;
> >
> >             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
> >                            "http ir:%V etag:%V", if_range, etag);
> >
> >             if (if_range->len == etag->len
> >                 && ngx_strncmp(if_range->data, etag->data, etag->len) ==
> 0) {
> >                 goto parse;
> >             }
> >         }
> >
> >         if (r->headers_out.last_modified_time != (time_t) -1) {
> >             if_range_time = ngx_http_parse_time(if_range->data,
> if_range->len);
> >
> >             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
> >                            "http ir:%d lm:%d",
> >                            if_range_time,
> r->headers_out.last_modified_time);
> >
> >             if (if_range_time == r->headers_out.last_modified_time) {
> >                 goto parse;
> >             }
> >         }
> >
> >         goto next_filter;
> >     }
> >
> > The new code is simpler and it implements the standard instead the old
> one.
> > Please comment my proposition.
> >
> > Anatoli Marinov
> >
> > _______________________________________________
> > nginx-devel mailing list
> > nginx-devel at nginx.org
> > http://mailman.nginx.org/mailman/listinfo/nginx-devel
>
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20140813/c7bc3cf6/attachment.html>


More information about the nginx-devel mailing list