Три недели назад я рассказывал про одну из конфигураций nginx для WordPress. С тех пор я получил пару отзывов, что так делать неправильно с ссылкой на конфигурацию, одобренную Игорем Сысоевым (автором nginx). Лежит она здесь:
This has the approval of Igor, the creator - you cannot get better than that.
На серверах, которые мне пришлось переводить на nginx, стояла версия 0.6.34 (версию 0.7.сколько-то там пришлось снести из-за того, что она сегфолтилась при обработке некоторых запросов, а анализировать core dump нет желания).
Рассмотрим предлагаемую конфигурацию:
listen 80;
server_name michaelshadle.com;
index index.php;
root /home/mike/web/michaelshadle.com/;
include /etc/nginx/defaults.conf;
include /etc/nginx/expires.conf;
error_page 404 = /wordpress/index.php?q=$request_uri;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:11000;
}
}
Начнём с того, что WordPress не требует параметр q
в запросе: достаточно взглянуть на правила, которые он генерирует для .htaccess. Но это всё, по сути, мелочи.
Такая конфигурация тоже является рабочей, но есть одно "но": если пользователь запрашивает несуществующий PHP-файл (например, опечатался), то ему прилетает экран с недружественным сообщением "No input file specified". К сожалению, для моего случая это было критично, ибо пользователь в такой ситуации должен был видеть немного другую страницу.
Есть еще одна конфигурация (правда, для Drupal), написанная Игорем Сысоевым. Если её перевести на WordPress, то получится предыдущий вариант, только хуже: помимо "No input file specified", на все 404 ошибки выдавался код 200 (!).
Конфигурация выглядела так:
server_name dev.example.com;
index index.php;
root /var/www/dev.example.com;
location / {
log_not_found off;
error_page 404 = @wordpress;
}
location @wordpress {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/dev.example.com/index.php;
include /etc/nginx/fastcgi_params;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/dev.example.com$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
Вот что получалось при обращении к dev.example.com/x/ph
:
Первый ответ 302 — это редирект с dev.example.com/x/ph
на dev.example.com/x/ph/
А второй ответ 200 — это то, что не должно случаться. Это, кстати, объясняет баг, который я нашел в All in One SEO Pack.
Взяв две рассмотренные конфигурации за основу, я создал третью, рабочую:
server_name dev.example.com;
index index.php;
root /var/www/dev.example.com;
location / {
log_not_found off;
error_page 404 = /index.php;
}
location = /index.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME /var/www/dev.example.com/index.php;
include /etc/nginx/fastcgi_params;
}
location ~ \.php$ {
if (!-e $request_filename) {
rewrite ^(.+)$ /index.php break;
}
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/dev.example.com$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
Так как Игорь Сысоев говорит, что обычно практикуемая прямая трансляция правил […] достойна всяческого порицания
, то такая конфигурация должна быть относительно хорошей. Хотя на мой взгляд, проверка существования файла делается что с rewrite, что без; видимо, в случае с nginx rewrite является довольно дорогой операцией (хотя, возможно, для -e
выполняется лишний stat
, не знаю).