<div dir="ltr">Hi Roman,<div><br></div><div>Thank you a lot for detailed explanation. </div><div>Initially I thought that <span style="background-color:rgb(234,245,255);color:rgb(68,77,86);font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:13px;white-space:pre-wrap">NGX_HTTP_SUBREQUEST_CLONE </span>option to <span style="background-color:rgb(230,255,237);color:rgb(0,92,197);font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px;white-space:pre-wrap">ngx_http_subrequest</span><span style="background-color:rgb(230,255,237);font-family:SFMono-Regular,Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px;white-space:pre-wrap"><font color="#444d56"> (</font></span>your latest fix in slice module - Slice filter: fetch slices in cloned subrequests) was intended to make full context in subrequest to be kept during redirects and because of minor bug it does not work in my case. </div><div><br></div><div>I'll need some solution for cases like this:</div><div><br></div><div>1. Origin redirects us (assuming that it not under our administration and we can't do anything)</div><div>2. Origin is missing a object and send us 404, so we have to fallback to other origin </div><div><br></div><div>If you have some suggestion how to workaround this tricky situation - I be very thankful. </div><div><br></div><div><br></div><div>George</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jun 13, 2017 at 2:44 PM, Roman Arutyunyan <span dir="ltr"><<a href="mailto:arut@nginx.com" target="_blank">arut@nginx.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi George,<br>
<span class=""><br>
On Mon, Jun 12, 2017 at 10:02:16AM +0300, George . wrote:<br>
> ​​Hi,<br>
> I've discovered following strange issue with http_slice_module<br>
> If I have a named location for internal 302 redirect and caching one slice<br>
> makes further request for whole object to brake upstream redirected request<br>
> (missing Rage header, see frame 254 in the attached capture ​<br>
</span>>  slice_redirect_problem.pcapng<br>
> <<a href="https://drive.google.com/a/ucdn.com/file/d/0ByZ2nt00gtJ2NmtqVUU3OVozNXM/view?usp=drive_web" rel="noreferrer" target="_blank">https://drive.google.com/a/<wbr>ucdn.com/file/d/<wbr>0ByZ2nt00gtJ2NmtqVUU3OVozNXM/<wbr>view?usp=drive_web</a>><br>
> ​ ).<br>
<br>
What happens is:<br>
<br>
- client requests 0-4m<br>
- nginx creates the request for the 1st slice and proxies it to 8081<br>
- after receiving 302, the request is redirected to<br>
  @fetch_from_redirected_origin and the first slice is saved in the cache<br>
<br>
Note that in @fetch_from_redirected_origin there's a completely separate<br>
slice context.  By this time nginx only knows what client sent.  Previous<br>
slice context is completely lost as well as all other modules' contexts.<br>
Coincidentally, it does what you expect because only the first slice was<br>
requested.<br>
<br>
Then you request the entire file:<br>
<br>
- client request the entire file<br>
- first slice is sent from the cache<br>
- nginx creates a subrequest for the 2nd slice: 4m-8m and proxies it to 8081<br>
- after receiving 302, the subrequest is redirected to<br>
  @fetch_from_redirected_origin<br>
<br>
After the redirect nginx does not have any idea that it should fetch the second<br>
slice.  Moreover, the $slice_range variable is not filled with actual range when<br>
first accessed in a subrequest (after error_page redirect it looks like the<br>
first access), so it remains empty.  That's why the entire file is requested.<br>
But even if the variable was valid, that would still be bad since the slice<br>
context is lost after error_page redirect.  You would get the whole file here<br>
instead of 4m-8m range.<br>
<br>
The takeaway is you should avoid using the slice module with redirects<br>
(error_page, X-Accel-Redirect) for fetching slices.  Instead you should proxy<br>
directly to the origin server.<br>
<span class=""><br>
>  If there is no cached slice everything is okey  (2nd capture​<br>
</span>>  slice_redirect_no_problem.<wbr>pcapng<br>
> <<a href="https://drive.google.com/a/ucdn.com/file/d/0ByZ2nt00gtJ2SUpnc2VVbzBKdWc/view?usp=drive_web" rel="noreferrer" target="_blank">https://drive.google.com/a/<wbr>ucdn.com/file/d/<wbr>0ByZ2nt00gtJ2SUpnc2VVbzBKdWc/<wbr>view?usp=drive_web</a>><br>
> ​)<br>
<br>
No, it's not ok.  The first redirect to @fetch_from_redirected_origin leads<br>
to caching all file slices instead of the first one.<br>
<div><div class="h5"><br>
> Problem appears in main branch and also  nginx/1.12 ... and may be in all<br>
> versions<br>
><br>
> nginx version: nginx/1.13.2<br>
> built by gcc 4.9.2 (Debian 4.9.2-10)<br>
> configure arguments: --prefix=/home/george/run/<wbr>nginx_hg<br>
> --with-http_slice_module<br>
><br>
><br>
><br>
><br>
> nginx.conf<br>
> user cdnuser cdnuser;<br>
> worker_processes  1;<br>
><br>
> error_log  logs/error.log  debug;<br>
><br>
> events {<br>
>     worker_connections  1024;<br>
> }<br>
><br>
><br>
> http {<br>
>     include       mime.types;<br>
>     default_type  application/octet-stream;<br>
><br>
><br>
>     sendfile        on;<br>
>     tcp_nopush      on;<br>
><br>
>     proxy_cache_path /home/george/run/nginx_hg/<wbr>cache/<br>
> keys_zone=zone_uid_default:4m levels=2:1 inactive=360d max_size=18329m;<br>
><br>
>     # our redirecting origin<br>
>     server {<br>
>         listen       8081;<br>
><br>
>         return 302 $scheme://127.0.0.1:8082$<wbr>request_uri;<br>
>     }<br>
><br>
>     # our final origin<br>
>     server {<br>
>         listen       8082;<br>
>         add_header Cache-Control "max-age=3600";<br>
>         root /home/george/run/nginx_hg/<wbr>root;<br>
>     }<br>
><br>
>     server {<br>
>         listen       8080;<br>
>         server_name  localhost;<br>
><br>
>         recursive_error_pages on;<br>
>         proxy_intercept_errors on;<br>
><br>
><br>
>         location / {<br>
>             slice             4m;<br>
>             proxy_cache       zone_uid_default;<br>
>             proxy_cache_key   $uri$is_args$args$slice_range;<br>
>             proxy_set_header  Range $slice_range;<br>
><br>
>             proxy_pass        <a href="http://localhost:8081" rel="noreferrer" target="_blank">http://localhost:8081</a>;<br>
><br>
>             error_page 301 302 307 = @fetch_from_redirected_origin;<br>
>         }<br>
><br>
>         location @fetch_from_redirected_origin {<br>
>             slice   4m;<br>
><br>
>             internal;<br>
><br>
>             set $my_upstream_http_location $upstream_http_location;<br>
><br>
>             proxy_cache       zone_uid_default;<br>
>             proxy_cache_key   $uri$is_args$args$slice_range;<br>
>             proxy_set_header  Range $slice_range;<br>
><br>
>             proxy_pass        $my_upstream_http_location;<br>
>         }<br>
>     }<br>
>  }<br>
><br>
><br>
> How to reproduce:<br>
><br>
> 1. Create some empty object in our emulated origin<br>
> mkdir /home/george/run/nginx_hg/root<br>
> dd if=/dev/zero of=/home/george/run/nginx_hg/<wbr>root/some_object  bs=64M<br>
> count=1<br>
><br>
> 2. Ask our caching proxy for one 4m slice, so it will be cached<br>
> curl -v -r 0-4194303 "<a href="http://127.0.0.1:8080/some_object" rel="noreferrer" target="_blank">http://127.0.0.1:8080/some_<wbr>object</a>" --header "Host:<br>
> localhost" -o /dev/null<br>
><br>
> 3. See it really there<br>
> george@george ~/run/nginx_hg $ head<br>
> /home/george/run/nginx_hg/<wbr>cache/81/c/<wbr>00214df7041ea53dd335ed5b055bfc<wbr>81<br>
> Ļ:Y˩:Y��:YVʜ�r � "593aa9cb-4000000"<br>
> KEY: /some_objectbytes=0-4194303<br>
> HTTP/1.1 206 Partial Content<br>
> Server: nginx/1.13.2<br>
> Date: Fri, 09 Jun 2017 14:16:20 GMT<br>
> Content-Type: application/octet-stream<br>
> Content-Length: 4194304<br>
> Last-Modified: Fri, 09 Jun 2017 13:59:39 GMT<br>
> Connection: close<br>
> ETag: "593aa9cb-4000000"<br>
><br>
> 4. This time request the whole object<br>
> curl -v  "<a href="http://127.0.0.1:8080/some_object" rel="noreferrer" target="_blank">http://127.0.0.1:8080/some_<wbr>object</a>" --header "Host: localhost" -o<br>
> /dev/null<br>
><br>
><br>
> ​​<br>
<br>
</div></div>> ______________________________<wbr>_________________<br>
> nginx-devel mailing list<br>
> <a href="mailto:nginx-devel@nginx.org">nginx-devel@nginx.org</a><br>
> <a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel" rel="noreferrer" target="_blank">http://mailman.nginx.org/<wbr>mailman/listinfo/nginx-devel</a><br>
<span class="HOEnZb"><font color="#888888"><br>
<br>
--<br>
Roman Arutyunyan<br>
______________________________<wbr>_________________<br>
nginx-devel mailing list<br>
<a href="mailto:nginx-devel@nginx.org">nginx-devel@nginx.org</a><br>
<a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel" rel="noreferrer" target="_blank">http://mailman.nginx.org/<wbr>mailman/listinfo/nginx-devel</a></font></span></blockquote></div><br></div>