Nginx 将 url 重写为 index.php 参数

Nginx rewrite urls as index.php parameters

我最近从 apache 切换到 nginx。 我的应用程序位于 /var/www/html 下并具有以下结构:

# tree -a /var/www/html
/var/www/html
├── .htaccess
├── folder1
│   ├── .htaccess
│   └── index.php
├── folder2
│   ├── .htaccess
│   └── index.php
├── index.php
├── file1.php
└── file2.php

所有目录下的.htaccess文件都一样:

# cat /var/www/html/.htaccess 
AddDefaultCharset UTF-8
Options +FollowSymLinks
Options -Indexes
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(assets)/ - [L,NE]

RewriteRule ^/?$ index.php?param1=main [QSA,L]
RewriteRule ^([-a-zA-Z0-9_]+)/$ index.php?param1= [QSA,L]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ index.php?param1=&param2= [QSA,L]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ index.php?param1=&param2=&param3= [QSA,L]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ index.php?param1=&param2=&param3=&param4= [QSA,L]

RewriteRule ^file1.xml$ file1.php [L]
RewriteRule ^file2.xml$ file2.php [L]

ErrorDocument 400 /error/400/
ErrorDocument 401 /error/401/
ErrorDocument 403 /error/403/
ErrorDocument 404 /error/404/
ErrorDocument 500 /error/500/

RedirectMatch (.*)\.inc /error/404/
RedirectMatch (.*)\.tpl /error/404/

现在我正在尝试构建 nginx 配置。我的目标是进行以下重写:

example.com or example.com/ -> example.com/index.php?param1=main
example.com/anything or example.com/anything/ -> example.com/index.php?param1=anything
example.com/anything/else or example.com/anything/else/ -> example.com/index.php?param1=anything&param2=else
etc...

folder1 和 folder2 也一样

example.com/folder1 or example.com/folder1/ -> example.com/folder1/index.php?param1=main
example.com/folder1/anything or example.com/folder1/anything/ -> example.com/folder1/index.php?param1=anything
etc...

Nginx 配置目前看起来像:

server {
    listen 443 ssl;
    server_name example.com;
    charset utf-8;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;

    root /var/www/html;
        index index.html index.htm index.php;

    location / {
    try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
} 

我使用了在线转换器并在 location / { 下放置了规则,但这没有用。 Url 喜欢示例。com/anything 显示 404 和示例。com/anything/ 尝试下载文件

有不止一种方法可以做到这一点。但以下示例使用命名位置将所有重写规则收集在一起。

location / {
    try_files $uri $uri/ @rewrite;
}
location @rewrite {
    rewrite ^/$ /index.php?param1=main? last;
    rewrite ^/([-a-zA-Z0-9_]+)/$ /index.php?param1=? last;
    rewrite ^/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ /index.php?param1=&param2=? last;
    rewrite ^/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ /index.php?param1=&param2=&param3=? last;
    rewrite ^/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ /index.php?param1=&param2=&param3=&param4=? last;

    rewrite ^/file1.xml$ /file1.php last;
    rewrite ^/file2.xml$ /file2.php last;
    return 404;
}

所有 Nginx URI 都以 / 开头。我假设默认操作是 return 404 如果 none 规则匹配。尾随 ? 可防止将任何原始参数附加到重写的 URI,如果要附加原始参数,请删除尾随 ?。有关详细信息,请参阅 this document

注意:在您的问题中,您声明要接受 example.com/anything/elseexample.com/anything/else/。这不是现有 .htaccess 所做的。要使结尾的 / 可选,请在 $ 之前的最后一个 / 之后添加一个 ?。例如:

rewrite ^/([-a-zA-Z0-9_]+)/?$ /index.php?param1=? last;

您可以对其他文件夹重复此模式,但看起来会很乱。此逻辑属于 index.php,但下面给出了一个 Nginx 示例:

location /folder1 {
    try_files $uri $uri/ @rewrite1;
}
location @rewrite1 {
    rewrite ^/folder1/?$ /folder1/index.php?param1=main? last;
    rewrite ^/folder1/([-a-zA-Z0-9_]+)/$ /folder1/index.php?param1=? last;
    ...
}

注意正则表达式和重写的URI都需要包含文件夹名称。