1. Handling arguments
Despite what Tero Kilkanen says, nginx is perfectly capable of handling arguments: this is done by using the args
and arg_
variables from the core module.
2. rewrite
context
As Glueon pointed out, rewrite
is usable in server
, location
and if
contexts, as the documentation states.
if
is to be avoided at all costs, so I won't be going inot details about it here.
Now should you use rewrite
in server
or location
?
In server
Blocks of rewrite
s will be considered sequentially, and the first matching will be used. Your configuration thus depends on the order of directives, which is bad (it is one of the things which are wrong with Apache).
See for yourself:
rewrite ^/(?<category>[^/]+)/(?<product>[^/]+) /products.asp?category=$category&product=$product&utm_source=wcl-ht last;
rewrite ^/games/(?<product>[^/]+) /games.asp?product=$product&utm_source=wcl-ht last;
will redirect to products.asp, while
rewrite ^/games/(?<product>[^/]+) /games.asp?product=$product&utm_source=wcl-ht last;
rewrite ^/(?<category>[^/]+)/(?<product>[^/]+) /products.asp?category=$category&product=$product&utm_source=wcl-ht last;
will redirect to games.asp
.
According to best practices, it is better to enclose regular expression routing directives (rewrite
, but also regex location
) inside prefix locations.
In location
You could rewrite the previous examples as
location /games {
rewrite ^/games/(?<product>[^/]+) /games.asp?product=$product&utm_source=wcl-ht;
}
location / {
rewrite ^/(?<category>[^/]+)/(?<product>[^/]+) /products.asp?category=$category&product=$product&utm_source=wcl-ht;
}
Using prefix locations, you ensure that whatever ordering you use, the result will always be the same.
3. Minimal configuration
Here is a minimal configuration aiming in the direction of what you wish.
There is no obvious translation rule from 2xu-glid to Glide%20SX%202012%20-%20%20Super%20Partno. If that depends on non-trivial conditions and complex checks, it is probably better to use scripting to do it. Using if
inside nginx is dangerous without knowing what you do and could wreak havoc. You can also use a bunch of nested locations to split your translation rules into modular units.
Note that I use a single rewrite here, so it does not need a flag nor does it need to be enclosed in a location. That is because there is only a signle way that configuration might be resolved.
Also note the use of return
at the end to ensure no file is ever tried to be served (the default behavior, when no suitable location is found, is to try to serve either a file or index.html from the requested directory
, depending on whether the URI ends with /
). Since no root
is defined, the default internally set would have been used.
events {
worker_connections 1024;
}
http {
default_type text/html;
server {
listen 80;
rewrite ^/(?<category>[^/]+)/(?<product>[^/]+) /products.asp?category=$category&product=$product&utm_source=wcl-ht last;
location /products.asp {
internal;
return 200 "Arguments: $args<br />arg_category: $arg_category<br />arg_product: $arg_product<br />arg_utm_source: $arg_utm_source";
}
return 404;
}
}