Архив метки: nginx

Работа WordPress на nginx + apache (постоянный 301 редирект)

В последнее время связка nginx + apache стала очень популярной среди администраторов веб-серверов. Эта связка довольно эффективна: nginx обеспечивает высокую скорость отдачи статического контента, кэширование, балансировку нагрузки, а apache, в свою очередь, давно признан стандартом де-факто среди веб-серверов за свою многофункциональность.

Ожидаемым было и появление хостинг-провайдеров, работающих с данной связкой. Чаще всего настройка nginx в данной связке ограничивается примерно такой конструкцией:

location / {
     index index.php index.html index.htm;
     try_files $uri $uri/ @proxy;
}
location ~ \.php$ {
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header Host $host;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_pass http://127.0.0.1;
}
location @proxy {
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header Host $host;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_pass http://127.0.0.1;
}

В таком случае установка WordPress вызовет бесконечную переадресацию с кодом 301. Дело в том, что nginx при получении запроса GET / будет подставлять индексный файл index.php и отправлять этот запрос на прокси, в качестве которого выступает apache. Apache, в свою очередь, запустит этот файл и за обработку запроса и формирование страницы примется WordPress. Для пущей красоты WordPress удалит из адресной строки index.php, который туда «дописал» nginx и вернет новый «красивый» урл с редиректом 301 клиенту. Клиент перейдет по нему, nginx допишет index.php и мы будем иметь то, что имели в самом начале.

Разные браузеры по-разному воспримут данную ситуацию, но бОльшая часть текущих версий после некоторого количества редиректов перестанет следовать им и выдаст страницу с ошибкой. Другими словами, сайт работать не будет.

Во избежание такой ситуации можно применить простой фикс: добавить в nginx еще один location, который будет отправлять запросы без указания конкретного файла сразу на apache без дописывания индексного файла. Таким образом, надо добавить примерно такую конструкцию:

location ~[^?]*/$ {
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header Host $host;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_pass http://127.0.0.1;
}

В таком случае запрос вида GET / будет передан на apache без изменений, wordpress его корректно обработает и вернет главную страницу сайта. При этом, естественно, индексный файл index.php должен быть определен и в конфигурации apache.