Undoing rewrite (for proxy_pass)

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:
URL encoding issue )

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:”
Module ngx_http_proxy_module

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?)

Greetings,
Thorben Thuermer
VSEO GmbH

PS1:
when working on this, i spent most time on finding out how to get nginx
running in gdb - is there some introduction to development documentation
where such information might be found/useful?

PS2:
before anybody asks, the configuration:
server {
listen 1.2.3.4:80;
server_name …;
root /var/www/…;
location / {
rewrite “^(lots of stuff here)$” /cache/(lots of
submatches) break;
try_files $uri $uri/ @apache;
}
location @apache {
rewrite ^(.*)$ $request_uri break; # useless
proxy_pass http://localhost;
}
}

Hello!

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

the problem i ran into was, that i needed to pass the original unprocessed

there the problem appears to be that r->valid_unparsed_uri is no longer

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 D.