Hi,<br><br><div class="gmail_quote">On Tue, Jan 31, 2012 at 5:13 PM, Maxim Dounin <span dir="ltr"><<a href="mailto:mdounin@mdounin.ru">mdounin@mdounin.ru</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hello!<br>
<div><div class="h5"><br>
On Tue, Jan 31, 2012 at 03:39:03PM -0800, Dave Bailey wrote:<br>
<br>
> Hi,<br>
><br>
> In ngx_http_upstream_rewrite_location(), r->upstream->rewrite_redirect may<br>
> replace the Location header value with a new value.  This value ends up<br>
> going through ngx_http_header_filter(), and if it's a relative URL, the<br>
> header filter adds a scheme and host to it.  However, if<br>
> r->upstream->rewrite_redirect declines (rc = NGX_DECLINED) to rewrite the<br>
> redirect, the value does not go through ngx_http_header_filter() even if it<br>
> is a relative URL.<br>
><br>
> Is this intended behavior?  If it is not, I attached a patch that sets<br>
> r->headers_out.location consistently.<br>
<br>
</div></div>I believe the intended behaviour is:<br>
<br>
1. If we got relative redirect from a backend and are going to pass it<br>
   to a client - don't touch it.  It's backend which breaks RFC, so<br>
   we don't care.<br>
<br>
   In the code path without upstream->rewrite_redirect set you may even see<br>
   special code to protect such redirects:<br>
<br>
    if (ho->value.data[0] != '/') {<br>
        r->headers_out.location = ho;<br>
    }<br>
<br>
    /*<br>
     * we do not set r->headers_out.location here to avoid the handling<br>
     * the local redirects without a host name by ngx_http_header_filter()<br>
     */<br>
<br>
    return NGX_OK;<br>
<br>
2. If we are about to produce our own relative redirect - make<br>
   sure it will be properly converted to absolute one by the header<br>
   filter.<br></blockquote><div><br>OK, thank you.  So this is intended.<br><br>The problem I am having is that the conversion to an absolute URL always uses a scheme of http:// unless the connection is an actual SSL connection.  This means that if SSL is terminated at a load balancer and nginx listens on a non-SSL port, rewritten redirects are converted to absolute with a scheme of http:// even though the actual request was https://.<br>
<br>I can work around it by having my callback emit an absolute URL with the correct scheme.  But, any interest in providing a way for nginx to do the same?  e.g.<br><br>server {<br>  # SSL terminated elsewhere<br>  listen 444;<br>
  # force https scheme on rewritten redirects converted to absolute urls<br>  scheme_https on;<br>}<br> </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

The code looks correct here.<br>
<br>
The problem I see is that if rewrite_redirect() returns<br>
NGX_DECLINED, the r->headers_out.location won't be set and it<br>
won't be possible to clear it in case we'll need to.<br>
<br>
The same applies to relative redirects from a backend though, and<br>
requires reconsidering of the "don't set r->headers_out.location<br>
to avoid handling by ngx_http_header_filter()" policy to make<br>
mentioned clearing indeed possible.<br>
<br>
Maxim Dounin<br>
<br>
_______________________________________________<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" target="_blank">http://mailman.nginx.org/mailman/listinfo/nginx-devel</a><br>
</blockquote></div><br>-dave<br><br>