nginx: перенаправление на сайт без www, включая все субдомены - PullRequest
0 голосов
/ 20 января 2019

Этот вопрос задавался по-разному миллион раз. Тем не менее я не могу найти ответ, достаточно общий, чтобы охватить все случаи.

Все, что я хочу, это удалить www с любого входящего URL, и я хочу, чтобы он применялся ко всем моим поддоменам. Вот мой конфиг nginx, который в остальном работает нормально:

# redirect HTTP to HTTPS, no www
server {
    listen      80;
    listen [::]:80;

    server_name ~^(?<www>www\.)(?<subdomain>.+)\.example\.com$;

    # redirect
    return 301 https://${subdomain}.example.com$request_uri;
}

#redirect HTTPS www to non-www
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name ~^(?<www>www\.)(?<subdomain>.+)\.example\.com$;

    # ssl config...

    # redirect
    return 301 https://${subdomain}.example.com$request_uri;
}

#default server
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name example.com *.example.com;

    # other calls below this point include
    # root dir
    # ssl config
    # security headers
    # various location blocks, specific to my project
    # error page
    # error/access logs...
}

Все эти сопоставления прекрасно обрабатываются конфигурацией выше:

Но это НЕ:

Можете ли вы помочь мне понять, что мне нужно изменить в моей конфигурации или как отладить это?

1 Ответ

0 голосов
/ 21 января 2019

Для блока http:

Благодаря HSTS обслуживает только клиентов, посещающих в первый раз.Таким образом, вы можете использовать простое перенаправление и выполнить удаление www. в блоках https.

Например:

server {
    listen      80;
    listen [::]:80;
    return 301 https://$host$request_uri;
}

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

Например:

server {
    listen      80;
    listen [::]:80;
    server_name   ~^(www\.)?(?<domain>.+)$;
    return 301 https://$domain$request_uri;
}

Подробнее см. в этом документе .


Дляблоки https:

Вам нужно регулярное выражение для захвата этой части имени домена после www..У вас есть два варианта:

Использовать два блока server (как у вас сейчас), но не ставить подстановочный оператор server_name во втором блоке.Вы можете использовать другое регулярное выражение (например, server_name ~example\.com$;) или вообще не указывать server_name и установить его по умолчанию.

Например:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name   ~^www\.(?<domain>.+)$;
    # ssl config...
    return 301 https://$domain$request_uri;
}
server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    # no server_name statement needed
    ...
}

Или использовать одно server заблокируйте и протестируйте переменную $http_host, используя оператор if.

Например:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name  .example.com;

    if ($http_host ~ ~^www\.(.+)$) { return 301 https://$1$request_uri; }
    ...
}

См. это предупреждение об использовании if.

...