Страница поддержки nginx с проблемой контента
Чтобы показать страницу обслуживания во время развертывания, я всегда использовал следующую конфигурацию в nginx:
if (-f /home/shared/system/maintenance.html) {
return 503;
}
error_page 503 @maintenance;
location @maintenance {
root /home/shared/errors;
rewrite ^(.*)$ /maintenance.html break;
}
И все было в порядке, пока мне не нужно было добавить статический контент на страницу обслуживания (изображения, таблицы стилей и т. Д.)
Нет статического контента, работающего с такими журналами в error.log:
2011/05/05 02:47:20 [notice] 13760#0: *6 "^(.*)$" matches "/some.jpg", client: x.x.x.x, server: server.com, request: "GET /some.jpg HTTP/1.1", host: "server.com"
2011/05/05 02:47:20 [notice] 13760#0: *6 rewritten data: "/maintenance.html", args: "", client: x.x.x.x, server: server.com, request: "GET /some.jpg 2 HTTP/1.1", host: "server.com"
Что логично - если я переписываю все в maintenance.html, это означает, что статический контент не является исключением.
Но я не могу найти правильного решения для перенаправления на каждый файл, кроме тех, которые физически существуют в root /home/shared/errors
папка.
PS. /home/shared/errors
не делит ресурсы с общей папкой проекта - это совершенно отдельная папка (даже без каких-либо ссылок на /current
для проекта.
6 ответов
Извини, Фрэнк Фармер, но это не работает.
Что работает, но не так аккуратно
И как работают запросы ->
Я использую правило № 1
if (-f /home/shared/system/maintenance.html) { return 503; }
это правило имеет поддержку именованного местоположения
location @maintenance
и для общего перенаправления на/maintenance.html
вroot /home/shared/errors
все работает.эта страница содержит и изображение
some.jpg
- для получения этого изображения браузер запускает новый запрос, и этот новый запрос снова попадает в правило №1все это было описано в первоначальном вопросе, НО
если я использую некоторые
if
как в ответах Фрэнка Фармера, я могу указать серверу на запрашиваемый файл, НО HTTP-ответ будет 503, и браузеры (все, кроме Safari, в моем тесте) выдают ошибки в консоли отладки и показывают изображение, но не обрабатывают CSS-файлы в одном и том же ситуация.И это очень важно.
Я попытался решить эту проблему, используя магию местоположения для моих новых запросов контента - это означает, что я должен:
не делайте
return 503
для запросов контента и вообще пропустить именованное местоположение.сделать изменение
root /home/shared/errors
потому что содержание обслуживания все еще там.
Наконец, у меня есть следующее решение:
Создайте
maintenance-static
папка для всего статического контента и изменения пути в моемmaintenance.html
статические таблицы файлов и обслуживаниязатем используйте эти правила (я считаю, что они описательны), которые заменяют
if (-f /home/shared/system/maintenance.html)
в первоначальном вопросе:set $can503 0; if (-f /home/shared/system/maintenance.html) { set $can503 1; } if ($uri ~* /maintenance-static/) { set $can503 0; } location /maintenance-static/ { root /home/shared/errors; } if ($can503 = 1) { return 503; }
Это решение работает без ошибок во всех браузерах и для множества страниц в shared/errors
папка, например maintenance.html, error.html, overload.html и т. д.
Это решение не совсем понятно - возможно, вы можете намекнуть, как я могу сделать его более аккуратным, но помните, что мы имеем дело с отдельными запросами (и отдельными процессами nginx для каждого файла / запроса в случае высокой загрузки и т. Д.) Для исходного html и его содержание мы не можем использовать одно правило с перенаправлением 503 для всех файлов.
Я провел два добрых часа в поисках ответа на эту проблему и, наконец, нашел этот пост. Похоже, это должно быть более распространенным. Мое решение упало где-то между Фрэнка и Уайла. Как утверждает Wile, некоторые браузеры (например, Chrome) предпочитают не отображать CSS/JS любых файлов, которые вернулись 503, даже если они полностью и правильно извлекли их.
Но есть исправление, которое менее хакерское, чем то, что сделал Уайл. Просто верните 200!
Мое полное решение было следующим:
error_page 503 @maintenance;
location @maintenance {
root /path_to_static_root;
if (!-f $request_filename) {
rewrite ^(.*)$ /rest_of_path/maintenance.html break;
}
return 200;
}
Работал как шарм.:)
location @maintenance {
root /home/shared/errors;
rewrite (some\.jpg|some2\.gif)$ /$1 break;
rewrite ^(.*)$ /maintenance.html break;
}
Это может работать без перечисления файлов из белого списка:
location @maintenance {
root /home/shared/errors;
if (!-f $request_filename) {
rewrite ^(.*)$ /maintenance.html break;
}
}
Это решение работает только с одним оператором if, а также гораздо более читабельно и понятно:
upstream unicorn {
server unix:/path/to/unicorn.sock;
}
server {
listen 3000 default deferred;
proxy_read_timeout 3600;
client_max_body_size 4G;
set_real_ip_from 0.0.0.0/0;
root /path/to/current/public;
try_files $uri/index.html $uri.html $uri @unicorn;
error_page 404 /404.html;
error_page 500 502 504 /500.html;
error_page 503 /system/maintenance.html;
location /404.html {
internal;
}
location /500.html {
internal;
}
location @unicorn {
if (-f $document_root/system/maintenance.html) {
return 503;
}
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
proxy_redirect off;
proxy_pass http://unicorn;
}
}
Я попробовал все предложения выше, и, к сожалению, они не работают, как ожидалось. Единственное решение, которое просто работает для меня, заключается в следующем:
location / {
if (-f /path/to/file/indicating/maintenance/mode) {
rewrite ^(.+)$ /maintenance/$1;
}
#... the rest of the "normal" logic
}
location /maintenance {
root /path/where/your/maintenance/root/is;
rewrite ^/maintenance/(.*)$ /$1 break;
try_files /$uri /index.html =404;
return 200;
}
Я знаю, это создает ненужное / обслуживаемое местоположение в нормальных условиях, но вы можете представить себе другой путь местоположения, который ваши пользователи никогда не угадывают:).
server {
listen 80;
server_name myserv.trunk;
autoindex off;
access_log /var/log/nginx/sitename-access.log;
location ^~ /static/ {
root /home/dev/myserv-site/;
}
location ~ /(?P<language>en)?/? {
uwsgi_pass unix:///tmp/uwsgi.sock;
include uwsgi_params;
error_page 502 @fallback;
error_page 503 @maintenance;
if (-f /home/dev/myserv-site/maintenance.active) {
return 503;
}
}
location @fallback {
root /home/dev/myserv-site/;
if ($language) {
rewrite ^(?!\/static\/)(.*)$ /static/html/502.$language.html break;
}
rewrite ^(?!\/static\/)(.*)$ /static/html/502.zh.html break;
}
location @maintenance {
root /home/dev/myserv-site/;
if ($language) {
rewrite ^(?!\/static\/)(.*)$ /static/html/503.$language.html;
}
rewrite ^(?!\/static\/)(.*)$ /static/html/503.zh.html break;
}
}
Вот пример экрана переводимого технического обслуживания (503) или ошибки 502. Если пользователь заходит на http://site.com/en/ будет отображаться английская страница (если существует файл maintenance.active). static dir находится внутри myserv-site dir.