Подтвердить что ты не робот

Nginx переписывает домен без префиксов www-prefixed

Я вижу, что Nginx Документация HttpRewriteModule содержит пример, чтобы переписать домен www-prefixed в домен без префикса www:

if ($host ~* www\.(.*)) {
  set $host_without_www $1;
  rewrite ^(.*)$ http://$host_without_www$1 permanent; # $1 contains '/foo', not 'www.mydomain.com/foo'
}

Как я могу сделать обратное - переписать домен, не связанный с www-prefixed, в домен с префиксом www? Я думал, может быть, я мог бы сделать что-то вроде следующего, но Nginx не любит вложенную инструкцию if.

if ($host !~* ^www\.) {                       # check if host doesn't start with www.
    if ($host ~* ([a-z0-9]+\.[a-z0-9]+)) {    # check host is of the form xxx.xxx (i.e. no subdomain)
        set $host_with_www www.$1;
        rewrite ^(.*)$ http://$host_with_www$1 permanent;
    }
}

Также я хотел, чтобы это работало для любого имени домена без явного указания Nginx переписать domain1.com → www.domain1.com, domain2.com → www.domain2.com и т.д., так как у меня есть большое количество домены для перезаписи.

4b9b3361

Ответ 1

Ну, я думаю, мне действительно не нужен внешний оператор "if", поскольку я все равно проверяю домены формы xxx.xxx. Для меня работает следующее, хотя оно не является надежным. Сообщите мне, есть ли лучшее решение.

    if ($host ~* ^([a-z0-9\-]+\.(com|net|org))$) {
        set $host_with_www www.$1;
        rewrite ^(.*)$ http://$host_with_www$1 permanent;
    }

Изменить: добавлен дефис в регулярное выражение, поскольку он является допустимым символом в имени хоста.

Ответ 2

Как указано в документации Nginx, вам следует избегать использования директивы if в Nginx, где это возможно, потому что, как только у вас есть if в вашей конфигурации ваш сервер должен оценить каждый отдельный запрос, чтобы решить, следует ли соответствовать этому if или нет.

Лучшим решением будет несколько директив сервера.

server {
        listen 80;
        server_name website.com;
        return 301 $scheme://www.website.com$request_uri;
}

server {
        listen 80;
        server_name www.website.com;
        ... 
}

Если вы пытаетесь использовать сайт с поддержкой SSL (HTTPS), у вас есть более или менее три разных варианта.

  • Настройте несколько IP-адресов, имеющих каждую директиву сервера, которые прослушивают свой собственный IP-адрес (или разные порты, если это опция для вас). Этим параметрам нужны сертификаты SSL для веб-сайта и веб-сайта www.website.com, поэтому у вас есть сертификат wild card, сертификат UNI (несколько доменов) или просто два разных сертификата.
  • Перепишите в приложении.
  • Используйте страшную директиву if.

Существует также опция использования SNI, но я не уверен, что это полностью поддерживается на данный момент.

Ответ 3

if ($host !~* ^www\.) {
    rewrite ^(.*)$ http://www.$host$1 permanent;
}

Ответ 4

if ($host ~* ^[^.]+\.[^.]+$) {
    rewrite ^(.*)$ http://www.$host$1 permanent;
}

Можно получить только допустимые имена хостов, потому что запрос никогда не сделает это на вашем сервере иначе, поэтому нет необходимости создавать собственную логику проверки.

Ответ 5

Документация nginx предостерегает от использования if для перезаписи. Пожалуйста, смотрите ссылку здесь: http://wiki.nginx.org/Pitfalls#Server_Name

Ответ 6

HTTP & HTTPS без условий:

server {
    listen          80;
    listen          443;
    server_name     website.com;

    return 301 $scheme://www.website.com$request_uri;
}
server {
    listen          80;
    listen          443 default_server ssl;
    server_name     www.website.com;

    # Your config goes here #
}

Ответ 7

Решение для нескольких доменов, работающее на nginx 1.17 для меня:

server {
        listen                                80;
        server_name                           .example.com;

        set $host_with_www                 $host;

        if ($host !~* www\.(.*)) {
            set $host_with_www www.$host;
        }

        return                                301 https://$host_with_www$request_uri;
}

В этом примере конфигурации дополнительно переписывает HTTP на HTTPS, если вы не хотите перезаписывать - замените https://на http://в return строке.

Если вы хотите сохранить протокол - используйте переменную $scheme.