Nginx rewrite non-existent files under sub directory with rewrite rules

Francis Daly francis at daoine.org
Thu Nov 27 19:21:32 UTC 2014


On Wed, Nov 26, 2014 at 05:35:06PM +0530, Joyce Babu wrote:

Hi there,

> I am trying to move a site with a large number (93) of .htaccess files from
> Apache to Nginx.

There isn't always a 1:1 correspondence between apache and nginx config,
so some things will differ.

The suggestions below do do part of what you ask, but probably do not
do all of what you want.

>    1. /test/abc/pics/ should redirect to /test/abc/wallpapers/

  location = /test/abc/pics/ { return 301 /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.

  location /test/abc/pics/ { try_files $uri /test/abc/pics/pic.php; }
  location = /test/abc/pics/pic.php {
    fastcgi_pass ...;
    fastcgi_param SCRIPT_FILENAME $document_root$request_uri;
    # and something about QUERY_STRING - details aren't in these requirements.
    # Possibly pic.php can be made to handle things without QUERY_STRING?
  }

>    3. /test/abc should redirect to /test/abc.html
>    4. /test/abc.html should be rewritten to /test/index.php

I'm not sure which parts of "redirect" and "rewrite" are important.

Possibly these two can be

  location /test/ { try_files $uri $uri.html @index; }
  location @index {
    fastcgi_pass ...;
    fastcgi_param SCRIPT_FILENAME $document_root/test/index.php;
  }

>    5. /test/abc/def/year-2014.php should be rewritten to
>    /test/abc/def/index.php

This might be a "return" or a "rewrite" or just a "fastcgi_pass" with
a suitable SCRIPT_FILENAME.

>    6. All static files (.gif, .jpg, .png, .mpg....) should be served
>    directly with a very long expiry time.

Each location with "try_files" should include the very long expiry time.

(Probably one "add_header" would do it.)

Note that "files" and "requests" are different things. It may make a
difference here.

>    7. All files ending in .html should be served directly. If the file does
>    not exist the request should be rewritten to /fallback.php

How does this fit in with the first requirement? Or are there no "html"
files in the /test/abc/pics/ hierarchy?

  location ~ \.html$ { try_files $uri @fallback; }

but the full location-matching rules should be consulted depending on
what actual files are present.

  location @fallback {
    fastcgi_pass ...;
    fastcgi_param SCRIPT_FILENAME $document_root/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

  location ~ \.php$ {
    try_files $uri @fallback;
    fastcgi_pass ...;
    fastcgi_param SCRIPT_FILENAME $document_root$request_uri;
  }
  
What "file" corresponds to a request that ends in "/"? You'll want

  index index.php;
  fastcgi_index index.php;

somewhere. Perhaps

  location ~ /$ {
    try_files $uri/ @fallback;
    fastcgi_pass ...;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  }

would work.

> *Configuration:*
 
Something seems to have mangled the whitespace here, making it hard to read.

But using the above an inspiration, hopefully you'll be able to find
something that fits your needs.

The basic idea is "avoid rewrite as much as possible".

>    1. Since the fallback rules are regular expressions, they are selected
>    instead of the location specific rules

Above, the fallback rules are internal or exact.

That should mostly avoid problems 2 and 3, since they no longer need to
happen (I think).

Cheers,

	f
-- 
Francis Daly        francis at daoine.org



More information about the nginx mailing list