undoing rewrite (for proxy_pass)

Maxim Dounin mdounin at mdounin.ru
Mon Feb 27 21:13:27 UTC 2012


On Mon, Feb 27, 2012 at 06:45:16PM +0100, Thorben Thuermer wrote:

> Hello,
> i recently tried to set up nginx as reverse-proxy in front of apache
> to offload serving of cached static versions of pages,
> where i needed to apply a rewrite to construct the local path of the
> cache files:
> * receive incoming requests
> * apply a rewrite-rule, use try_files to serve files if they exist
> * otherwise proxy_pass the original request to apache
> the problem i ran into was, that i needed to pass the original unprocessed
> request to apache, as it may contain script parameters that get broken by
> processing.
> (the best reference to this issue that i found is this:
>  http://mailman.nginx.org/pipermail/nginx/2010-April/019905.html )
> as i do not even need to forward a rewritten version,
> this solution should apply:
> "If it is necessary to transmit URI in the unprocessed form then directive
> proxy_pass should be used without URI part:"
> -- http://wiki.nginx.org/NginxHttpProxyModule#proxy_pass
> but this does not work anymore after a rewrite was applied, as the
> rewritten version will be transmitted.
> the natural method to undo a rewrite would appear to be:
>  rewrite .* $request_uri  break;
> but this replaces the request with a processed version!
> i found the code for constructing the request in:
> src/http/modules/ngx_http_proxy_module.c:ngx_http_proxy_create_request
> the if-block starting at line ~910 appears to pick the request-uri
> to be used in the request.
> there the problem appears to be that r->valid_unparsed_uri is no longer
> set after rewrites were applied, so it will never choose to use the
> unparsed uri!
> i simply ignored r->valid_unparsed_uri, and replaced the whole block with:
>         unparsed_uri = 1;
>         uri_len = r->unparsed_uri.len;
> and now my reverse-proxying works as required.
> (ofcourse i broke the other cases by hardcoding this, but that's not an
>  issue for me.)
> i am wondering if there might be interest in including a proper solution
> for this situation in nginx.
> (or maybe there is one already and i missed it?)

Something like this should do the trick:

    proxy_pass http://backend$request_uri;

Though it has an additional side-effect of using resolver for a 
"backend" at run-time if it's not an ip address nor a name of an 
upstream{} block.

Maxim Dounin

More information about the nginx mailing list