back-reference from if() and rewrite?

Ingo Lafrenz lists at der-ingo.de
Thu Jun 8 14:42:19 UTC 2017


Hi,

Let me give you a couple of hints (esp when you come from Apache):
- stop thinking like you have apache. nginx and apache are fundamentally 
different when it comes to rewriting
- nginx rewrites only consider the location part of the URL during 
matching, so whenever you need to do work based on mutliple arguments, 
you are in trouble with nginx (not really, it's just very different and 
sometimes almost impossible)
- if is evil (google it! ;-)). If you need multiple ifs you are probably 
doing something in the webserver which should be done elsewhere (e.g. 
backend).
- there is no need to parse arguments with regex, use the $arg_ 
variables of nginx (argument id will be variable $arg_id, see 
http://nginx.org/en/docs/varindex.html)
- your back references in if don't work, because you have also back 
references in your rewrite, so the rewrite overwrites your if back 
reference variables
- you can use named back references, e.g. id=(?<id>[^&]*) which creates 
a variable named $id
- always try to create locations with = or with ^~, use regex only if 
you really have to, also make sure you understand the precedence of 
location evaluation rules
- maps are very powerful and useful in nginx. you can replace a lot of 
if logic with clever maps and rewrites and internal locations (see 
example at end)

Have a look at this:
# create locations for urls that should not be processed by your rewrite 
logic (see your question nr 2)
location ^~ /rss/mobSpecCycle {}
location ^~ /rss/mobSpecTheme {}
# actual rewrite logic happens here
location ^~ /rss/mobSpec {
   # only rewrite if id argument is present, otherwise you have a 
redirect loop
   if ($arg_id) {
     rewrite ^/rss/mobSpec([^\/]+)/$ 
/rss/mobSpec$1/mobSpec$1_$arg_id.html? permanent;
   }
}

I have made one simplification: I do not consider the "daily" argument, 
since it was not used in your example.
Please take this only as a starting point, I haven't put much testing 
into this.

Here the example with maps (map is global, not inside server block):
map $uri $cacheable_uri {
   default "/NOCACHE";
   "/catalog/" "/CACHE";
   "/main/" "/CACHE";
   "~^/products/.*" "/CACHE";
}
and then in your server:
location / {
   rewrite ^ $cacheable_uri$uri last;
}
location ^~ /CACHE/ {
   internal;
   rewrite ^/CACHE/(.*) /$1 break;
   proxy_cache cache_zone;
   # any directive you only want to make for cacheable uris
   proxy_pass http://backend;
}
location ^~ /NOCACHE/ {
   internal;
   rewrite ^/NOCACHE/(.*) /$1 break;
   proxy_pass http://backend;
}

This is just a simplified example to show how to avoid ifs using maps 
and rewrites.
This rewrites every url and prepends it with either CACHE or NOCACHE. 
Then I have internal locations (you cant access them directly, only 
through rewrites) where I delete the prefix again, but inside the 
location I have specific directives. I hope that gets you started to 
"think in nginx way"!
Good luck with nginx, you will love it!

Cheers, Ingo =;->

> Hello,
>
> I need to translate following rule from apache to nginx:
>
> RewriteCond %{QUERY_STRING} id=([^&]*) [NC,OR]
> RewriteCond %{QUERY_STRING} daily=([^&]*) [NC]
> RewriteCond %{REQUEST_URI} !mobSpecCycle [NC]
> RewriteCond %{REQUEST_URI} !mobSpecTheme [NC]
> RewriteRule ^rss\/mobSpec([^\/]+)/?$ /rss/mobSpec$1/mobSpec$1_%1.html
> [QSA,NC,L]
>
> which, e.g. rewrites
>
> /rss/mobSpecArticle/?id=26422
>
> into
>
> /rss/mobSpecArticle/mobSpecArticle_26422.html
>
> I started as follows
>
> if ($args ~ id=([^&]*)|daily=([^&]*)) {
>     rewrite ^/rss\/mobSpec([^\/]+)/?$ /rss/mobSpec$1/mobSpec$1_$2.html
> last;
> }
>
> However I don't know how to backrefernce id=([^&]*) in the rewrite rule?
> I put $2 there, but it doesn't work... apache has %1 for
> back-referencing matches from the RewriteCond.
>
> 1. How do I back-referencing matches from if () in nginx within
> following rewrite?
>
> 2. Any ideas how I can add the last two condition?
> RewriteCond %{REQUEST_URI} !mobSpecCycle [NC]
> RewriteCond %{REQUEST_URI} !mobSpecTheme [NC]
>
> Thank you in advance!
>
>
> _______________________________________________
> nginx mailing list
> nginx at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx




More information about the nginx mailing list