nginx rewrite rule to convert URL segments to query string parameters
I'm setting up an nginx server for the first time, and having some trouble getting the rewrite rules right for nginx.
The Apache rules we used were:
See if it's a real file or directory, if so, serve it, then send all requests for /
to Director.php
DirectoryIndex Director.php
If the URL has one segment, pass it as rt
RewriteRule ^/([a-zA-Z0-9\-\_]+)/$ /Director.php?rt=$1 [L,QSA]
If the URL has two segments, pass it as rt
and action
RewriteRule ^/([a-zA-Z0-9\-\_]+)/([a-zA-Z0-9\-\_]+)/$ /Director.php?rt=$1&action=$2 [L,QSA]
My nginx config file looks like:
server {
...
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
How do I get the URL segments into Query String Parameters like in the Apache rules above?
UPDATE 1
Trying Pothi's approach:
# serve static files directly
location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires 30d;
}
location / {
try_files $uri $uri/ /Director.php;
rewrite "^/([a-zA-Z0-9\-\_]+)/$" "/Director.php?rt=$1" last;
rewrite "^/([a-zA-Z0-9\-\_]+)/([a-zA-Z0-9\-\_]+)/$" "/Director.php?rt=$1&action=$2" last;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
This produces the output No input file specified.
on every request. I'm not clear on if the .php
location gets triggered (and subsequently passed to php) when a rewrite in any block indicates a .php file or not.
UPDATE 2
I'm still confused on how to setup these location blocks and pass the parameters.
location /([a-zA-Z0-9\-\_]+)/ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME ${document_root}Director.php?rt=$1{$args};
include fastcgi_params;
}
UPDATE 3
It looks like the root directive was missing, which caused the No input file specified.
message. Now that this is fixed, I get the index file as if the URL were /
on every request regardless of the number of URL segments.
It appears that my location regular expression is being ignored.
My current config is:
# This location is ignored:
location /([a-zA-Z0-9\-\_]+)/ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index Director.php;
set $args $query_string&rt=$1;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location / {
try_files $uri $uri/ /Director.php;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index Director.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Disclaimer: None of the following are tested. Please use it with caution. If anything goes wrong, please turn on debugging as mentioned at http://nginx.org/en/docs/debugging_log.html .
See if it's a real file or directory, if so, serve it,
then send all requests for / to Director.php
This may be achieved with...
server {
index Directory.php;
location / {
try_files $uri $uri/ /Directory.php;
}
}
The index
directive is enough for directory index. To send all requests to Director.php, then location block is needed.
If the URL has one segment, pass it as rt
You may try the following...
rewrite "^/([a-zA-Z0-9\-\_]+)/$" "/Director.php?rt=$1" last;
Please remember the quotes around the rewrites. It is preferable to use quotes, and is needed on certain conditions (that is mentioned in the link provided earlier by @jerm).
If the URL has two segments, pass it as rt and action
You may try the following...
rewrite "^/([a-zA-Z0-9\-\_]+)/([a-zA-Z0-9\-\_]+)/$" "/Director.php?rt=$1&action=$2" last;
Please note that I haven't done anything for QSA in the above examples. You may try $args
variable in Nginx to pass the existing query string to the new query string. Ref: http://nginx.org/en/docs/http/ngx_http_core_module.html#variables
I hope that helps to arrive at the full working solution!