Nginx rewrite non-existent files under sub directory with rewrite rules
Joyce Babu
joyce at joycebabu.com
Wed Nov 26 12:05:06 UTC 2014
Hi everyone,
I am trying to move a site with a large number (93) of .htaccess files from
Apache to Nginx.
There are over 800 rewrite rules to convert. To optimize performance, I
have decided to
place the rules under separate nested location blocks (61 blocks in total).
But I am having problem with rewriting some of the rules. I have created a
sample scenario to explain the problem.
*Requirements:*
1. /test/abc/pics/ should redirect to /test/abc/wallpapers/
2. /test/abc/pics/800/a.jpg should be served directly, if the file is
present. If it does not exist, then the request should be rewritten to
/test/abc/pics/pic.php, which will create the file on first request.
Subsequent requests will be served directly.
3. /test/abc should redirect to /test/abc.html
4. /test/abc.html should be rewritten to /test/index.php
5. /test/abc/def/year-2014.php should be rewritten to
/test/abc/def/index.php
6. All static files (.gif, .jpg, .png, .mpg....) should be served
directly with a very long expiry time.
7. All files ending in .html should be served directly. If the file does
not exist the request should be rewritten to /fallback.php
8. All files ending in .php or / should be executed by PHP-FPM. If the
file does not exist it should be rewritten to /fallback.php
*Configuration:*
index index.php; # # Location Specific Rules # location /test/abc/ {
location /test/abc/pics/ { # For ensuring 'serve directly, if file exists'
condition of Rule 2 try_files $uri @rewrite_pics; } location /test/abc/def/
{ try_files $uri $uri/index.php @rewrite_def; } } location /test/ { rewrite
"^/test/([a-z-]+)$" /test/$1.html permanent; # Rule 3 rewrite
"^/test/([a-z-]+).html$" /test/index.php?symbol=$1 last; # Rule 4 }
location @rewrite_pics { rewrite "^/test/abc/pics/$" /test/abc/wallpapers/
permanent; # Rule 1 rewrite "^/test/abc/pics/([0-9]+)/(.*)$"
/test/abc/pics/pic.php?width=$1&height=$1&pic=$2 last; # Rule 2 } location
@rewrite_def { rewrite "(?i)^/test/abc/def/year-([a-z]+).php$"
/test/abc/def/index.php?year=$1 last; # Rule 5 } # # Fallback Rules #
location ~*
\.(gif|jpg|jpeg|png|ico|3gp|flv|mpg|mpeg|mp4|mp3|swf|txt|xml|pdf|zip)$ {
expires 1M; # Rule 6 try_files $uri /404.php; } location ~
(\.php|\.html|/)$ { try_files $uri "${uri}index.php" /fallback.php =404; #
Rules 7 & 8 include php-fpm.conf; }
*php-fpm.conf *
include fastcgi.conf;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
*Problem*
1. Since the fallback rules are regular expressions, they are selected
instead of the location specific rules
2. If I use ~ prefix for all location specific rules, then the fallback
rules are never executed. Request for /test/abc/pics/800/a.jpg will be
rewritten to /test/abc/pics/pic.php which will again match the same
location config. So the file is not executed and is downloaded as is.
3. So, I added 'include php-fpm.conf;' to all location blocks (except
named locations). But this causes all requests under /test/abc/pics/
(including existing .jpg files) to pass to the PHP-FPM. Which leads to an
access denied error, since only .php extension is allowed by
security.limit_extensions.
What am I doing wrong here? Is there a simple way to have all existing
files served depending on their extension and only non existent files match
the location blocks / rewrite rules?
Thanks & Regards,
Joyce Babu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx/attachments/20141126/07520a10/attachment.html>
More information about the nginx
mailing list