<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
Hi guys,
<div class=""><br class="">
</div>
<div class="">I’m having an nginx instance where I utilise the nginx slice module to slice upstream mp4 files when using proxy_cache.</div>
<div class=""><br class="">
</div>
<div class="">However, I have an interesting origin where if sending a range request (which happens when the slice module is enabled), to a file that’s less than the slice range, the origin returns a 200 OK, but with the range related headers such as content-range,
 but obviously the full file is returned since it’s within the requested range.</div>
<div class=""><br class="">
</div>
<div class="">When playing the MP4s through Google Chrome and Firefox it works fine when going through the nginx proxy instance, however, it somehow breaks Safari (both on MacOS, and iOS) - I guess Safari is more strict.</div>
<div class="">When playing directly through the origin it works fine in all browsers.</div>
<div class=""><br class="">
</div>
<div class="">The md5 of response from the origin remains the same, so it’s not that the response itself is an invalid MP4 file, and even if you compare the cache files on disk with a “working” origin and the “broken” origin (one sends a 206 Partial Content,
 another sends 200 OK) - the content of the cache files remain the same, except obviously the header section of the cache file.</div>
<div class=""><br class="">
</div>
<div class="">The origin returns a 206 status code, only if the file exceeds the slice size, so if I configure a slice size of 5 megabyte, only files above 5 megabytes will give 206s. Anything under 5 megabytes will result in a 200 OK with content-range and
 the correct content-length,</div>
<div class=""><br class="">
</div>
<div class="">Looking in the slice module itself I see:</div>
<div class=""><a href="https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_slice_filter_module.c#L116-L126" class="">https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_slice_filter_module.c#L116-L126</a> </div>
<div class=""><br class="">
</div>
<div class=""><br class="">
<font face="Courier New" class="">    if (r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) {<br class="">
        if (r == r->main) {<br class="">
            ngx_http_set_ctx(r, NULL, ngx_http_slice_filter_module);<br class="">
            return ngx_http_next_header_filter(r);<br class="">
        }<br class="">
<br class="">
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,<br class="">
                      "unexpected status code %ui in slice response",<br class="">
                      r->headers_out.status);<br class="">
        return NGX_ERROR;<br class="">
    }</font></div>
<div class=""><br class="">
</div>
<div class="">This seems like the slice module expects a 206 status code to be returned, however, later in the same function <a href="https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_slice_filter_module.c#L200-L211" class="">https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_slice_filter_module.c#L200-L211</a> </div>
<div class=""><br class="">
</div>
<div class=""><br class="">
<font face="Courier New" class="">    if (r->headers_out.status == NGX_HTTP_PARTIAL_CONTENT) {<br class="">
        if (ctx->start + (off_t) slcf->size <= r->headers_out.content_offset) {<br class="">
            ctx->start = slcf->size<br class="">
                         * (r->headers_out.content_offset / slcf->size);<br class="">
        }<br class="">
<br class="">
        ctx->end = r->headers_out.content_offset<br class="">
                   + r->headers_out.content_length_n;<br class="">
<br class="">
    } else {<br class="">
        ctx->end = cr.complete_length;<br class="">
    }</font></div>
<div class=""><br class="">
</div>
<div class="">There it will do an else statement if the status code isn’t 206.</div>
<div class="">So would this piece of code ever be reached, since there’s the initial error?</div>
<div class=""><br class="">
</div>
<div class="">Additionally I don’t see in RFC7233 that 206 responses are an absolute requirement, additionally I don’t see content-range being prohibited/forbidden to be used for 200 OK responses.</div>
<div class="">Now, if one have a secondary proxy that modifies the response headers in between the origin returning 200 OK with the Content-Range header, and then strip out the Content-Range header, the nginx slice module seems to handle it fine, so somehow
 the combination of 200 OK and a Content-Range header being present seems to break the slice module from functioning.</div>
<div class=""><br class="">
</div>
<div class="">I’m just curious why this happens within the slice module, and if there’s any possible solution for it (like allowing the combination of 200 OK and Content-Range, since those two would still indicate that the origin/upstream supports range requests)
 - obviously it would be nice to fix the upstream server but sometimes that’s sadly not possible.</div>
<div class=""><br class="">
</div>
<div class="">I know the parts of the slice module haven’t been touched for years, so obviously it works for most people, just dipping my toes here to see if there’s a possible solution other than disabling slice when an origin returns 200 OK for files smaller
 than the slice size.</div>
<div class=""><br class="">
</div>
<div class="">Thanks in advance</div>
<div class=""><br class="">
</div>
<div class="">Best Regards,</div>
<div class="">Lucas Rolff</div>
</body>
</html>