Страница обслуживания nginx с проблемой контента - PullRequest
17 голосов
/ 13 мая 2011

Чтобы показать страницу обслуживания во время развертывания, я всегда использовал следующую конфигурацию в 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 ]

11 голосов
/ 16 мая 2011

Извините, Фрэнк Фармер, но это не работает.

Что работает, но не так аккуратно:

И как работают запросы ->

  1. Я использую правило # 1

    if (-f /home/shared/system/maintenance.html) {
        return 503;
    }
    

    Это правило имеет поддержку именованного местоположения location @maintenance, и для общего перенаправления на /maintenance.html на root /home/shared/errors все работает.

  2. эта страница содержит и изображение some.jpg - для получения этого изображения браузер запускает новый запрос, и этот новый запрос снова обращается к правилу # 1

    , все это было описано в исходном вопросе, НО

    если я использую магию if, как в ответах Фрэнка Фармера, я могу указать серверу на запрашиваемый файл, НО HTTP-ответ будет 503, и браузеры (все, кроме Safari в моем тесте) выдают ошибки в консоли отладки и делаютпокажите изображение, но не обрабатывайте CSS-файлы в той же ситуации.

    И это очень важно.

  3. Я попытался решить эту проблему, используя магию местоположения для моего нового контента-запросы - это означает, что я должен:

    1. НЕ return 503 fo• Запросы контента и вообще пропускают указанное местоположение.

    2. действительно измените root /home/shared/errors, потому что содержание обслуживания все еще там.

  4. Наконец-то у меня есть следующее решение:

    1. создать папку maintenance-static для всего статического содержимого и пути изменения в моем файле maintenance.html и таблицах стилей обслуживания-статики

    2. далее используйте эти правила (я считаю, что они описательны), которые заменяют один 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. Для всех файлов.

10 голосов
/ 05 ноября 2011

Я потратил добрых два часа на поиски ответа на эту проблему и, наконец, нашел этот пост. Похоже, это должно быть более распространенным. Мое решение упало где-то между Фрэнка и Уайла. Как утверждает 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;
}

работал как шарм. :)

4 голосов
/ 13 мая 2011
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;
    }
}
2 голосов
/ 11 мая 2012

это решение работает только с одним оператором 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;
        }
}
1 голос
/ 07 апреля 2015

Я перепробовал все предложения, приведенные выше, и, к сожалению, они не работают должным образом. Единственное решение, которое мне подходит, это следующее:

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;
}

Я знаю, он создает ненужное / обслуживаемое местоположение в нормальных условиях, но вы можете представить себе другой путь к местоположению, о котором ваши пользователи никогда не догадаются:).

1 голос
/ 29 марта 2012
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.

...