webdevops nginx - 从 url 中删除 .php 要求
webdevops nginx - remove .php requirement from url
我有一个基于 webdevops/php-nginx:7.2
的 docker,我正在尝试配置 nginx 以将带有或不带有 .php 扩展名的请求路由到适当的文件。
如果 abc.php
存在,我需要 /abc
和 /abc.php
才能路由到 abc.php
。其他一切都将转到 index.php
当前设置如下:
Dockerfile
包含
WEB_DOCUMENT_ROOT=/app/public
COPY docker/opt/docker/etc /opt/docker/etc/
opt/docker/etc/nginx/conf.d/10-location-root.conf
server {
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?_url=$uri&$args;
}
}
/app/public
包含
index.php
abc.php
目前此配置将所有内容路由到 index.php
,/abc.php
除外。尝试点击 /abc
到 index.php
的路线。
谢谢:)
编辑: 使用 Ivan 的回答 docker 记录垃圾邮件:
app_1 | -> Executing /opt/docker/bin/service.d/nginx.d//10-init.sh
app_1 | 2020-10-20 10:31:59,273 INFO success: nginxd entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
app_1 | nginx: [emerg] unknown "_uri" variable
app_1 | 2020-10-20 10:31:59,287 INFO exited: nginxd (exit status 1; not expected)
如果我正确理解这个系统是如何工作的,让我们从以下两个文件开始:
/opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
rewrite ^ $uri.php last;
}
/opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
try_files $uri /<DOCUMENT_INDEX>?_url=$uri&$args;
fastcgi_pass php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_read_timeout <PHP_TIMEOUT>;
}
以上配置有一处严重缺陷。如果请求的 URI 不是现有 PHP 文件的名称(有或没有 .php
扩展名),$uri
内部 nginx 变量值将始终以 .php
结尾由于 @extensionless-php
命名位置内的 rewrite
规则。这将导致以下结果(假设文件 /app/public/some/path.php
不存在):
/some/path
=> /index.php?_url=/some/path.php
/some/path.php
=> /index.php?_url=/some/path.php
要解决此问题,我们可以将原始 $uri
变量值保存在 extensionless-php
命名位置中:
/opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
set $original_uri $uri;
rewrite ^ $uri.php last;
}
/opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
try_files $uri /<DOCUMENT_INDEX>?_url=$original_uri&$args;
fastcgi_pass php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_read_timeout <PHP_TIMEOUT>;
}
这个配置比较好,但还是有瑕疵。如果请求的URI以.php
结尾,而/app/public
目录下没有相应的PHP文件,则$original_uri
变量不会被初始化,_url
查询参数将作为空字符串传递给后端:
/some/path
=> /index.php?_url=/some/path
/some/path.php
=> /index.php?_url=
对于某些 Web 应用程序来说这可能没问题(空的 _url
查询参数总是意味着无效的路由),但是如果我们想要获得原始 URI,无论它是什么,我们必须做什么?我们可以借助 map
指令(一个 非常 强大的 nginx 特性)来实现它。但是所有 map
块都应该在 server
块之外声明,所以我们需要一个额外的文件:
/opt/docker/etc/nginx/conf.d/10-map.conf
map $_uri $original_uri {
"" $uri;
default $_uri;
}
/opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
set $_uri $uri;
rewrite ^ $uri.php last;
}
/opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
try_files $uri /<DOCUMENT_INDEX>?_url=$original_uri&$args;
fastcgi_pass php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_read_timeout <PHP_TIMEOUT>;
}
这个 map
块意味着 $original_uri
变量将等于 $uri
如果它没有被修改($_uri
变量没有被初始化并且是空的).如果 $_uri
变量不为空,则意味着原始 $uri
已被修改,并且 $_uri
变量现在保持其原始值,因此 $original_uri
变量的值将是设置为 $_uri
。此配置应适用于将原始 URI 保留为 _url
查询参数的任何请求。
我有一个基于 webdevops/php-nginx:7.2
的 docker,我正在尝试配置 nginx 以将带有或不带有 .php 扩展名的请求路由到适当的文件。
如果 abc.php
存在,我需要 /abc
和 /abc.php
才能路由到 abc.php
。其他一切都将转到 index.php
当前设置如下:
Dockerfile
包含
WEB_DOCUMENT_ROOT=/app/public
COPY docker/opt/docker/etc /opt/docker/etc/
opt/docker/etc/nginx/conf.d/10-location-root.conf
server {
index index.html index.php;
location / {
try_files $uri $uri/ /index.php?_url=$uri&$args;
}
}
/app/public
包含
index.php
abc.php
目前此配置将所有内容路由到 index.php
,/abc.php
除外。尝试点击 /abc
到 index.php
的路线。
谢谢:)
编辑: 使用 Ivan 的回答 docker 记录垃圾邮件:
app_1 | -> Executing /opt/docker/bin/service.d/nginx.d//10-init.sh
app_1 | 2020-10-20 10:31:59,273 INFO success: nginxd entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
app_1 | nginx: [emerg] unknown "_uri" variable
app_1 | 2020-10-20 10:31:59,287 INFO exited: nginxd (exit status 1; not expected)
如果我正确理解这个系统是如何工作的,让我们从以下两个文件开始:
/opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
rewrite ^ $uri.php last;
}
/opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
try_files $uri /<DOCUMENT_INDEX>?_url=$uri&$args;
fastcgi_pass php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_read_timeout <PHP_TIMEOUT>;
}
以上配置有一处严重缺陷。如果请求的 URI 不是现有 PHP 文件的名称(有或没有 .php
扩展名),$uri
内部 nginx 变量值将始终以 .php
结尾由于 @extensionless-php
命名位置内的 rewrite
规则。这将导致以下结果(假设文件 /app/public/some/path.php
不存在):
/some/path
=> /index.php?_url=/some/path.php
/some/path.php
=> /index.php?_url=/some/path.php
要解决此问题,我们可以将原始 $uri
变量值保存在 extensionless-php
命名位置中:
/opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
set $original_uri $uri;
rewrite ^ $uri.php last;
}
/opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
try_files $uri /<DOCUMENT_INDEX>?_url=$original_uri&$args;
fastcgi_pass php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_read_timeout <PHP_TIMEOUT>;
}
这个配置比较好,但还是有瑕疵。如果请求的URI以.php
结尾,而/app/public
目录下没有相应的PHP文件,则$original_uri
变量不会被初始化,_url
查询参数将作为空字符串传递给后端:
/some/path
=> /index.php?_url=/some/path
/some/path.php
=> /index.php?_url=
对于某些 Web 应用程序来说这可能没问题(空的 _url
查询参数总是意味着无效的路由),但是如果我们想要获得原始 URI,无论它是什么,我们必须做什么?我们可以借助 map
指令(一个 非常 强大的 nginx 特性)来实现它。但是所有 map
块都应该在 server
块之外声明,所以我们需要一个额外的文件:
/opt/docker/etc/nginx/conf.d/10-map.conf
map $_uri $original_uri {
"" $uri;
default $_uri;
}
/opt/docker/etc/nginx/vhost.common.d/10-location-root.conf
location / {
try_files $uri $uri/ @extensionless-php;
}
location @extensionless-php {
set $_uri $uri;
rewrite ^ $uri.php last;
}
/opt/docker/etc/nginx/vhost.common.d/10-php.conf
location ~ \.php$ {
try_files $uri /<DOCUMENT_INDEX>?_url=$original_uri&$args;
fastcgi_pass php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_read_timeout <PHP_TIMEOUT>;
}
这个 map
块意味着 $original_uri
变量将等于 $uri
如果它没有被修改($_uri
变量没有被初始化并且是空的).如果 $_uri
变量不为空,则意味着原始 $uri
已被修改,并且 $_uri
变量现在保持其原始值,因此 $original_uri
变量的值将是设置为 $_uri
。此配置应适用于将原始 URI 保留为 _url
查询参数的任何请求。