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:
- /test/abc/pics/ should redirect to /test/abc/wallpapers/
- /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. - /test/abc should redirect to /test/abc.html
- /test/abc.html should be rewritten to /test/index.php
- /test/abc/def/year-2014.php should be rewritten to
/test/abc/def/index.php - All static files (.gif, .jpg, .png, .mpg…) should be served
directly with a very long expiry time. - All files ending in .html should be served directly. If the file
does
not exist the request should be rewritten to /fallback.php - 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
- Since the fallback rules are regular expressions, they are
selected
instead of the location specific rules - 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. - 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 B.