有两个主机,每个主机都有一个 PHP-FPM 池 - one.com 和 two.com。我希望 one.com/two 能够通过并使用 two 的池显示 two.com,但我似乎遇到了困难。
通过alias
和try_files
,我已成功从通过one.com/two/path/to/asset.ext 提供的two.com文件中获取静态资产,但PHP请求例如one.com/two/index.php
(以及对two文件中不存在的文件的请求)似乎回退到最后一条规则并显示one.com的应用程序404页面。
这是 one.com 的位置配置:
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~* ^/two$ {
return 301 /two/;
}
location /two/ {
alias /srv/two.com/public/;
try_files $uri $uri/ /two/index.php$is_args$args;
}
location ~* ^/two/(.+\.php)$ {
alias /srv/two.com/public/$1;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/7.1-two.com.sock;
}
location ~* \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/7.1-one.com.sock;
}
snippets/fastcgi-php.conf
:
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;
# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include snippets/fastcgi_params.conf;
$1
因为别名似乎是正确的 - 我用return 302 /$1 which would redirect the client to the expected path (e.g.
/two/foo.php ->
/foo.php 替换了该块)
此外,如果我放置deny all;
最后两个位置块中的任何一个,它会阻止所有受影响的请求(/two/*.php,/two/path/to/nonexistent.file)
就像它没有在第一个 fastcgi 传递位置块处停止一样 - 我是否遗漏了应该告诉它停止的东西?
-
编辑:添加break;
没有停止,并且尝试通过在每个位置块中添加标题来调试只显示最后一个通用 php 块中存在的标题。
-
编辑2:
事实证明,fastcgi_split_path_info
需要进行更改才能考虑目录前缀。
因此,我撕掉了代码片段文件并在位置块内对其进行了一些修改:
location ^~ /two {
alias /data/srv/nginx/two.com/public/;
try_files $uri $uri/ /two/index.php$is_args$args;
location ~* ^\/two.+\.php$ { # have also tried with just \.php$
alias /srv/two.com/public/$1;
fastcgi_split_path_info ^/two(.+\.php)().*$; # the second group is deliberately empty.
try_files $fastcgi_script_name =404;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include snippets/fastcgi_params.conf;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/php/7.1-two.com.sock;
}
}
这似乎使位置块正常工作,除非我遍历更深的一个级别,例如/two/account
- 再次显示one.com 的 404 页面。
我在外部位置放置了一个拒绝,这会阻止请求,但在内部位置放置一个拒绝却不会阻止请求。出于某种原因,它决定使用原始代码中的最后一个正则表达式位置。
答案1
所以我找到了问题和一个不太好的解决方案。
根据 nginx 文档,存在一个已知错误,当使用try_files
和alias
同一个上下文中(不会被修复)。
这nginx bugtracker 对该错误进行了讨论包括案例和实际发生的情况。
因此,我最终需要做的是更改我的配置如下:
首先,需要从alias
行中删除尾随的斜杠,因为try_files
斜杠会在其自身上添加。
其次,try_files
第一个块中的 需要在请求名称前加上两个前缀,而不是/two/index.php
(/two/two/index.php
因为别名会在确定下一个位置块之前剪掉第一部分)。
最后,对于 PHP,我需要调整REQUEST_URI
so 而不是/two/index.php
将其作为 传递/index.php
。
我在主 nginx 配置中创建了一个变量映射,如下所示:
http {
# ...
map $request_uri $prefixless_request_uri {
"~^/[^/]+(?P<path>.*)$" $path;
}
然后在我调用fastcgi_pass
覆盖传递的值之前引用它。
fastcgi_param REQUEST_URI $prefixless_request_uri;