如何在 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
文件一起提供。
这可以解决,但您必须停止使用 index
和 try_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;
我目前使用以下配置在我的 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
文件一起提供。
这可以解决,但您必须停止使用 index
和 try_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;