如何在 nginx 上从 /file.php 重定向到 /file?

How redirect from /file.php to /file on nginx?

我目前使用以下配置在我的 nginx 服务器上隐藏 url 的 .php 扩展名:

location / {
    try_files $uri $uri/ @extensionless-php;
    index index.html index.htm index.php;
}

location ~ \.php$ {
    try_files $uri =404;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}

location @extensionless-php {
    rewrite ^(.*)$ .php last;
}

这工作得很好,但我怎样才能让 nginx 不允许添加 .php 扩展名?。在我的示例中,如果您手动删除 .php 它会起作用,但如果您添加它,它会永久保留在 url.

要使用 HTTP 301 代码永久重定向这些请求,请尝试

rewrite ^(.*)\.php$  permanent;

将此指令放在 location 块之前。

更新

在回答这个问题后,OP 又问了一个问题(现在被删除了)——如果你有以下 webroot 结构怎么办:

webroot
|
+-- index.php (PHP file)
|
+-- somename.php (PHP file)
|
+-- somename (folder)
|   |
|   +-- index.php (PHP file)
|
+-- someothername (folder)
    |
    +-- index.php (PHP file)

以前的解决方案无法提供 somename.php 文件,因为对 http://example.com/somename 的请求将被 try_files 指令重定向到 http://example.com/somename/,下一轮将是与 somename/index.php 文件一起提供。

这可以解决,但您必须停止使用 indextry_files 指令并使用您自己的请求处理逻辑模拟它们的行为。这就是我最终得到的结果:

map $original_uri $maybe_slash {
    ~/$      '';
    default  '/';
}

server {

    ...

    if ($original_uri = '') {
        set $original_uri $uri;
    }

    # redirect requests of '/somepath/somefile.php' to '/somepath/somefile'
    rewrite ^(.*)\.php$  pemanent;

    location / {

        # this emulates 'try_files $uri $uri/ ...' directive behavior and redirects '/some/path'
        # to '/some/path/' if 'some/path.php' file does not exists, but 'some/path' folder exists
        # and there are 'some/path/index.html' file in that folder
        set $check_redirect $rewrited$maybe_slash;
        if ( $check_redirect = '1/' ) {
           return 301 $original_uri/$is_args$args;
        }

        if ( -f $document_root$uri.php ) { rewrite ^ $uri.php last; }

        # this emulates 'index index.php index.html' directive behavior
        if ( -f $document_root$uri${maybe_slash}index.php ) {
            set $rewrited 1;
            rewrite ^ $uri${maybe_slash}index.php last;
        }
        if ( -f $document_root$uri${maybe_slash}index.html ) {
            set $rewrited 1;
            rewrite ^ $uri${maybe_slash}index.html last;
        }

        # if a request for an absent resource should be served with some backend
        # controller, it is ok to use some 'try_files' directive here like
        # try_files $uri /index.php?path=$original_uri;

    }

    location ~ \.php$ {

        # this emulates 'try_files $uri $uri/ ...' directive behavior and redirects '/some/path'
        # to '/some/path/' if 'some/path.php' file does not exists, but 'some/path' folder exists
        # and there are 'some/path/index.php' file in that folder
        set $check_redirect $rewrited$maybe_slash;
        if ( $check_redirect = '1/' ) {
           return 301 $original_uri/$is_args$args;
        }

        # no 'try_files $uri =404'  or 'include snippets/fastcgi-php.conf' here, this location
        # can be reached only if requested PHP file is really exists in webroot folder
        include fastcgi.conf;
        fastcgi_param SCRIPT_FILENAME $document_root$uri;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;

    }

}

使用上面给出的配置和 webroot 结构

  • http://example.com/ 的请求将与 webroot/index.php 文件一起提供;
  • http://example.com/somename 的请求将与 webroot/somename.php 文件一起提供;
  • http://example.com/somename.php 的请求将被重定向到 http://example.com/somename 并与 webroot/somename.php 文件一起提供;
  • http://example.com/somename/ 的请求将与 webroot/somename/index.php 文件一起提供;
  • http://example.com/someothername 的请求将被重定向到 http://example.com/someothername/(因为不存在 webroot/someothername.php 文件)并与 webroot/someothername/index.php 文件一起提供。

关于自定义 HTTP 错误页面的重要说明

如果您有一些自定义错误页面,例如 webroot/error/404.php 用于 HTTP 404 错误,而不是像

这样定义它的通常方式
error_page 404 /error/404.php;

您需要跳过该文件的 .php 扩展名:

error_page 404 /error/404;