Nginx переписывает домен без префикса www в домен с префиксом www - PullRequest
39 голосов
/ 27 октября 2009

Я вижу, что документация по Nginx HttpRewriteModule содержит пример для перезаписи домена с префиксом www в домен без префикса 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 в домен с префиксом 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 и т. Д., Поскольку у меня большое количество домены для перезаписи.

Ответы [ 6 ]

62 голосов
/ 20 марта 2013

Как отмечено в документации 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), у вас есть более или менее три различных варианта.

  1. Настройте несколько IP-адресов, чтобы каждая серверная директива прослушивала свой собственный IP (или разные порты, если это вариант для вас). Для этой опции требуются сертификаты SSL как для website.com , так и для www.website.com , так что у вас есть сертификат подстановочного знака, сертификат UNI (несколько доменов) или просто два разных сертификаты.
  2. Переписать в приложении.
  3. Используйте страшную директиву if.

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

15 голосов
/ 07 ноября 2009
if ($host !~* ^www\.) {
    rewrite ^(.*)$ http://www.$host$1 permanent;
}
13 голосов
/ 28 октября 2009

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

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

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

6 голосов
/ 22 сентября 2010
if ($host ~* ^[^.]+\.[^.]+$) {
    rewrite ^(.*)$ http://www.$host$1 permanent;
}

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

4 голосов
/ 29 декабря 2012

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

1 голос
/ 24 марта 2019

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

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 #
}
...