У меня есть настройка блока местоположения, чтобы перехватывать все запросы файлов и отправлять их PHP-FPM
:
location / {
try_files $uri /routing.php?$args;
fastcgi_pass unix:/opt/local/var/run/php54/php-fpm-www.sock;
include /documents/projects/intahwebz/intahwebz/conf/fastcgi.conf;
}
Это работает и правильно передает запрос на PHP-FPM
либо к точному существующему файлу php, который был запрошен, либо с routing.php
установить как запускаемый сценарий.
Я попытался добавить страницу с ошибкой, чтобы, если файл маршрутизации когда-либо был удален или недоступен по другим причинам, отображалась страница с ошибкой, а не страница с ошибкой по умолчанию Nginx:
location / {
try_files $uri /routing.php?$args /50x_static.html;
fastcgi_pass unix:/opt/local/var/run/php54/php-fpm-www.sock;
include /documents/projects/intahwebz/intahwebz/conf/fastcgi.conf;
}
Это останавливает routing.php
файл не обслуживается, и вместо него отображается страница 50x_static.html. Запросы к существующему файлу PHP по-прежнему работают, т.е. переходят по URL-адресу /dynamic.php
Я понимаю, что последний параметр в try_files
команда немного волшебная:
Если файл не найден, выполняется внутреннее перенаправление на последний параметр. Обратите внимание, что только последний параметр вызывает внутреннее перенаправление, предыдущие просто устанавливают внутренний указатель URI. Последний параметр - резервный URI и должен существует, иначе возникнет внутренняя ошибка.
Изучая, почему error_page нарушила конфигурацию, я понял, что для конфигурации, которая работает (без страницы статической ошибки), Nginx действительно дважды соответствует запросу согласно журналу перезаписи Nginx при попытке получить корневой URL "/ ":
"^/proxy/(\d+)/(\w+)/(.+)\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)$" does not match "/", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test"
"^/proxy/(\d+)/(.+)\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)$" does not match "/", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test"
"^/staticImage/(\w+)/(.+)\.([^\.]*)$" does not match "/", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test"
"^/proxy/(\d+)/(\w+)/(.+)\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)$" does not match "/routing.php", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test"
"^/proxy/(\d+)/(.+)\.(gif|png|jpg|jpeg|GIF|PNG|JPG|JPEG)$" does not match "/routing.php", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test"
"^/staticImage/(\w+)/(.+)\.([^\.]*)$" does not match "/routing.php", client: 127.0.0.1, server: basereality.com, request: "GET / HTTP/1.1", host: "basereality.test"
т.е. запрос поступает как /
, то try_files
не обслуживает файл и поэтому перезаписывает запрос из /
к /routing.php
а затем повторно обрабатывает запрос.
Почему файлы try не обслуживают routing.php
файл на первом проходе? Он существует и доступен, иначе его бы не обслужили во второй раз.
РЕДАКТИРОВАТЬ
Удален несвязанный конфиг.
В процитированной вами документации прямо говорится, что «выполняется внутреннее перенаправление на последний параметр». Внутреннее перенаправление обрабатывается так же, как и исходный запрос от клиента - это включает обработку rewrite
операторы на уровне сервера, которые вы видите в журнале. Однако если какой-либо другой try_files
за исключением того, что последний соответствует существующему файлу, запрос обрабатывается с использованием location
конфигурация, где try_files
оператор находится, и второго совпадения не будет.
Что касается ваших правил, вы пытались просто опустить $args
в try_files
?
location / {
try_files $uri /routing.php /50x_static.html;
fastcgi_pass unix:/opt/local/var/run/php54/php-fpm-www.sock;
include /documents/projects/intahwebz/intahwebz/conf/fastcgi.conf;
}
Обратите внимание, что $uri
не содержит $args
слишком; параметры запроса по-прежнему будут передаваться в бэкэнд FastCGI через QUERY_STRING
параметр, который предположительно установлен в вашем fastcgi.conf
:
fastcgi_param QUERY_STRING $query_string;
И если ни то, ни другое $uri
ни /routing.php
присутствуют в виде файлов, запрос будет перенаправлен на /50x_static.html
и обрабатывается в соответствии с location = /50x_static.html
в вашей конфигурации (но вторая итерация попыток перезаписи все равно будет выполнена, потому что ваши правила перезаписи размещены на уровне сервера).
Одна очень подозрительная деталь вашей конфигурации заключается в том, что вы передаете все файлы через PHP независимо от расширения файла - это очень необычно и может вызвать проблемы безопасности из-за выполнения кода PHP в файле, где это не ожидалось.
У Сергея все было правильно; добавление $args
в команду try_files останавливает сопоставление файла и, таким образом, отправляет Nginx раунд в другом цикле обработки, что является нечетным, поскольку это то, что Nginx пример говорит делать.
Если вы будете точно следовать примеру с:
try_files $uri $uri/ /index.php?q=$uri&$args;
Если $uri
и $uri/
не существует, Nginx перейдет к последнему волшебному параметру. Он даже не пытается сопоставить файл, а вместо этого повторно обрабатывает запрос, устанавливая новый путь к /index.php
и $args
теперь быть q=$uri&$args
.
С другой стороны, если у вас есть другое значение в try_files
после index.php например
try_files $uri $uri/ /index.php?q=$uri&$args /50x_static.html;
Nginx ищет файл с именем /index.php?q=$uri&$args
и его явно не существует, поэтому он переходит на /50x_static.html
и перерабатывает это.
Так как $uri
перезаписывается, когда Nginx повторно обрабатывает запрос, избегая некоторых тонких изменений. Если вы настроили свою конфигурацию так:
set $originalURI $uri;
try_files $uri $uri/ /index.php /50x_static.html;
fastcgi_param QUERY_STRING q=$originalURI&$query_string;
Файл, который ищет Nginx, это /index.php
это правильное имя, поэтому nginx остановит там обработку. Мы должны скопировать $uri
переменная как try_files
изменяет его, и поэтому было бы просто /index.php
если бы мы просто использовали его после try_files.