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