Есть два хоста с пулом PHP-FPM каждый - one.com и two.com. Я хотел бы, чтобы one.com/two прошел и показал two.com с использованием пула two, но, похоже, у меня возникли трудности.
Через alias
и try_files
, Мне удалось получить статические ресурсы из файлов two.com, обслуживаемых через. one.com/two/path/to/asset.ext, но запросы PHP, например one.com/two/index.php
(и запросы к файлам, которых нет в двух файлах), похоже, возвращаются к последнему правилу и вместо этого показывают страницу 404 приложения one.com.
Вот конфигурация местоположения для 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
- что снова показывает страницу 404 на one.com.
Я сбросил отказ во внешнем местоположении, который останавливает запрос, но вместо этого отказ во внутреннем местоположении не блокирует запрос. По какой-то причине он решает использовать последнее местоположение регулярного выражения в исходном коде.
Итак, я нашел проблему и не очень хорошее решение.
Согласно документации nginx, существует известная ошибка, когда с помощью try_files
и alias
в том же контексте (что не будет исправлено).
В nginx bugtracker обсуждает ошибку включая дела и то, что на самом деле происходит.
Поэтому мне пришлось изменить мою конфигурацию следующим образом:
Во-первых, необходимо удалить косую черту в конце alias
линии как try_files
добавит косую черту на себя.
Во-вторых, try_files
в первом блоке нужно было дважды префикс имени запроса - вместо /two/index.php
, это стало /two/two/index.php
(потому что псевдоним обрежет первую часть перед определением следующего блока местоположения).
Наконец, для PHP мне нужно было настроить REQUEST_URI
так что вместо /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;