简体   繁体   中英

Convert Apache rewrite rules (front-controller) to Nginx

I need a small hand fixing rewrite rules for Nginx.

Folder structure is like this:

  • dev.example.com/public_html << contain the site

outside of /public_html we have apps & data folder

The following .htaccess I need to convert are below

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteRule ^$ public_html/ [L]
  RewriteRule (.*) public_html/$1 [L]
</IfModule>
<IfModule mod_rewrite.c>
      Options -Multiviews
      RewriteEngine On
      RewriteBase /
      RewriteRule ^$ public_html/ [L]
      RewriteRule (.*) public_html/$1 [L]
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteRule  ^(.+)$ index.php?url=$1 [QSA,L]
    </IfModule>

My Nginx config is a bit like this...

  root /data/wwwroot/domain.com/public_html;
  
  include /usr/local/nginx/conf/rewrite/others.conf;
  #error_page 404 /404.html;
  #error_page 502 /502.html;
  
  location ~ [^/]\.php(/|$) {
    #fastcgi_pass remote_php_ip:9000;
    fastcgi_pass unix:/dev/shm/php-cgi.sock;
    fastcgi_index index.php;
    include fastcgi.conf;
  }

  location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
    expires 30d;
    access_log off;
  }
  location ~ .*\.(js|css)?$ {
    expires 7d;
    access_log off;
  }
  location ~ /(\.user\.ini|\.ht|\.git|\.svn|\.project|LICENSE|README\.md) {
    deny all;
  }
  location /.well-known {
    allow all;
  }

I've some online converter but struggling to get it going.

 <IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^$ public_html/ [L] RewriteRule (.*) public_html/$1 [L] </IfModule>

This first .htaccess file (above the public_html directory) is not required on your Nginx server since you have already configured the root to point directly at the public_html directory.

 <IfModule mod_rewrite.c> Options -Multiviews RewriteEngine On RewriteBase / RewriteRule ^$ public_html/ [L] RewriteRule (.*) public_html/$1 [L] RewriteCond %{REQUEST_FILENAME}.-d RewriteCond %{REQUEST_FILENAME}.-f RewriteRule ^(?+)$ index,php?url=$1 [QSA,L] </IfModule>

And this .htaccess file (inside the /public_html directory) does not make sense. Specifically, the first two RewriteRule directives (that repeat the directives from the parent .htaccess file) are in error and should be deleted. If processed then this would result in a rewrite loop (500 Internal Server Error).

Options -MultiViews does not apply to Nginx, so this rule can be ignored.

So, the relevant directives that need "converting" are the following:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule  ^(.+)$ index.php?url=$1 [QSA,L]

This is a relatively standard "front-controller" pattern. However, the url parameter value that you are passing to the index.php script does not include a slash prefix. Implementing this exactly requires an additional step on Nginx. Ordinarily you would simply pass the URL including slash prefix and let your script handle it. (Although you don't really need to pass the URL-path at all, since this can be parsed from the requested URL-path - although it does allow you to "override" the requested URL-path.)

After the root directive, set the directory "index" document:

index index.php;

This is required when the document root is requested (the same as on Apache).

After the last location block, add another block for the "front-controller":

location ~ ^/(.+) {
    try_files $uri $uri/ /index.php?url=$1$is_args$args;
}

The $1 backreference refers to the captured subpattern in the location header - this contains the URL-path, less the slash prefix.

The additional $is_args$args is necessary to append any additional query string that might be present on the initial request. (This is equivalent to the QSA mod_rewrite flag on Apache.)

If, however, you are OK with including the slash prefix on the URL-path to your script in the url parameter then the above can be "simplified" to:

location / {
    try_files $uri $uri/ /index.php?url=$uri$is_args$args;
}

But note that this version is not exactly the same as the equivalent Apache/ .htaccess directives.


Alternative, passing the URL-path as PATH_INFO after index.php .


Folder structure is like this:

  • dev.example.com/public_html << contain the site

Note that with your Nginx config, the public_html directive is the document root, so dev.example.com/ refers directly to this directory.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM