How to edit url and pass forward to wsgi?

Hello,

If I have the following directive:

 location ~ /staging/dog/.*/info/cat {
     rewrite /staging/(.+) /$1 break;
     include uwsgi_params;
     uwsgi_pass 127.0.0.1:3130;
 }

then a call to http://127.0.0.1/staging/doc/v0.2/info/cat gets passed
through to my wsgi handler fine. Now if I leave that directive in place,
but put the following one before it, then get “502 Bad Gateway”:

 location ~ /dog/.*/info/cat {
     include uwsgi_params;
     uwsgi_pass 127.0.0.1:3030;
 }

Nothing else was changed. The route is different, the port is different.
Why would this affect the other one? Is it that I’m somehow “breaking”
out and then matching the other one?

My question is: how do I not break out? I’ve tried removing “break”
but the effect seems exactly the same (i.e. undesired). How do I make it
so that the url is rewritten and then pass immediately on? I.e. I want
to not leave the location box once I’ve matched. Is this possible?

I’ve searched the internet for a long time and read the docs here:
Module ngx_http_rewrite_module but I’ve had
no success so far. Thanks a lot for any help.

Cheers,
Thomas

On Thu, Sep 03, 2015 at 12:44:09AM -0400, Thomas Nyberg wrote:

Hi there,

location ~ /staging/dog/.*/info/cat {

“~” means “regex match”.

You haven’t anchored the regex, so a request for /staging/dog/x/info/cat
will match this, but so will a request for /a/staging/dog/x/info/cat/b

directive in place, but put the following one before it, then get
“502 Bad Gateway”:

location ~ /dog/.*/info/cat {

This also is matched by a request for /staging/dog/x/info/cat.

For regex locations, first match wins. So this location is chosen to
process this request.

Nothing else was changed. The route is different, the port is
different. Why would this affect the other one? Is it that I’m
somehow “breaking” out and then matching the other one?

No. Your request matches the first regex location, so uses the first
regex location.

Possibly you want

location ~ ^/dog/.*/info/cat

or

location ~ ^/dog/.*/info/cat$

or maybe just

location ^~ /dog/

depending on what the full plan is.

I.e. I want to not leave the location box once I’ve matched.
Is this possible?

Yes, it’s what you are already doing.

You’re just not in the location block you think you are in.

http://nginx.org/r/location

f

Francis D. [email protected]

Thank you very much for the response. It’s working now. I didn’t realize
that the regular expressions needed anchoring. I’m used to regular
expressions where ‘.*’ is needed for the functionality you refer to.

On a related note, is there some way to log the location choices that
are made? I tried using a debug logging mode, but it was far too
low-level (on the level of memory allocations). Of course I could have
the routes’ outputs go to certain files to figure it out, but if there
was a way to log something like "taking route
/staging/doc/.*/info/cat" it would make things much easier.

Thanks for the help!

On Thu, Sep 03, 2015 at 08:40:36AM -0400, Thomas Nyberg wrote:

Hi there,

On a related note, is there some way to log the location choices
that are made? I tried using a debug logging mode, but it was far
too low-level (on the level of memory allocations). Of course I
could have the routes’ outputs go to certain files to figure it out,
but if there was a way to log something like “taking route
/staging/doc/.*/info/cat” it would make things much easier.

The debug log should have a bunch of “test location:” lines, followed
by one “using configuration” line. That’s the location that is being
used for this request.

Other than that, the rules at Module ngx_http_core_module and at
How nginx processes a request should make it
straightforward to determine which location is used for this request.

And now that you know that regexes are not implicitly anchored, it
should
be clear what is going on.

It’s even easier if there are only prefix locations in use.

Cheers,

f

Francis D. [email protected]