Ответ 1
Очень хороший вопрос! Но это вообще невозможно, если вы не вызываете какой-то script, который устанавливает правильный код ответа.
Рабочее решение только с nginx и no if
Директива try_files
выполняет только внутреннее перенаправление для последнего оператора. Но мы можем объединить его с директивой index
и заставить внутреннее перенаправление.
# This will be the HTML file to display for the 503 error.
error_page 503 /maintenance/maintenance.html;
# Let nginx know that this particular file is only for internal redirects.
location = /maintenance/maintenance.html {
internal;
}
# Any request that starts with the maintenance folder is 503!
location ^~ /maintenance/ {
return 503;
}
# Instead of checking if a file exists and directly delivering it we check
# if a certain directory exists and trigger our index directive which will
# perform an internal redirect for us.
location / {
expires epoch;
try_files /maintenance/ $uri $uri/ /index.php?$args;
}
Любые недостатки с этим методом?
- Фактически 301 перенаправляется в каталог вместо того, чтобы оставаться на одном и том же URL (поисковые системы).
- Браузерное кэширование 301 перенаправления может быть проблемой, поэтому я добавил
expires epoch
в блок местоположения.
Другие решения?
Файл конфигурации nginx
Вместо создания файла HTML, почему бы не создать файл конфигурации nginx и просто перезагрузить процесс?
- Намного лучше!
- Легче понять!
- Никаких побочных эффектов!
Конфигурация nginx может выглядеть следующим образом (обратите внимание, что этот if
вовсе не злой):
error_page 503 /maintenance.html;
location / {
include maintenance.conf;
if ($maintenance = 1) {
return 503;
}
try_files $uri $uri/ /index.php?$args;
}
Содержимое файла maintenance.conf
:
set $maintenance 0;
И если вы хотите активировать режим обслуживания (в своей оболочке):
echo set $maintenance 1;> maintenance.conf && service nginx reload
Более продвинутый для друзей оболочки Вы могли бы даже расширить init script с помощью этого, например мой LSB-совместимый, заменив следующий блок в конце файла:
*)
echo "Usage: ${NAME} {force-reload|reload|restart|start|status|stop}" >&2
exit 1
;;
Со следующим блоком:
maintenance)
echo "set $maintenance 1;" > /etc/nginx/maintenance.conf && service nginx reload;
;;
production)
echo "set $maintenance 0;" > /etc/nginx/maintenance.conf && service nginx reload;
;;
*)
echo "Usage: ${NAME} {force-reload|reload|restart|start|status|stop|maintenance|production}" >&2
exit 1
;;
И теперь вы можете просто выполнить следующую команду (включая автозаполнение), чтобы перейти в режим обслуживания:
service nginx maintenance
Или вернуться в производство:
service nginx production
С файлом script/PHP
Другим чрезвычайно простым подходом, который будет работать как шарм, является использование файла PHP, который его обрабатывает.
location / {
try_files /maintenance.php $uri $uri/ /index.php?$args;
}
Ваш PHP файл будет выглядеть точно так же, как ваш HTML файл, вам нужно только добавить к нему начало (предполагая PHP 5.4 +):
<?php http_response_code(503) ?><!doctype html>
<html>
<head>
<!-- ... more html ... -->