Nginx без www для www и www для no-www - PullRequest
470 голосов
/ 30 октября 2011

Я использую nginx в облаке Rackspace после урока и искал в сети, и пока не могу отсортировать его.

Я хочу, чтобы www.mysite.com пошел наmysite.com как обычно в .htaccess по SEO и другим причинам.

Мой / etc / nginx / sites-available / www.example.com.vhost config:

server {
       listen 80;
       server_name www.example.com example.com;
       root /var/www/www.example.com/web;

       if ($http_host != "www.example.com") {
                 rewrite ^ http://example.com$request_uri permanent;
       }

Я тоже пробовал

server {
       listen 80;
       server_name example.com;
       root /var/www/www.example.com/web;

       if ($http_host != "www.example.com") {
                 rewrite ^ http://example.com$request_uri permanent;
       }

Я тоже пробовал.Обе вторые попытки дают ошибки цикла перенаправления.

if ($host = 'www.example.com' ) {
rewrite ^ http://example.com$uri permanent;
}

Мой DNS настроен как стандарт:

site.com 192.192.6.8 A type at 300 seconds
www.site.com 192.192.6.8 A type at 300 seconds

(примеры IP-адресов и папок использовались в качестве примеров и помогали людям в будущем).Я использую Ubuntu 11.

Ответы [ 17 ]

772 голосов
/ 31 октября 2011

HTTP Solution

Из документации "правильный способ - определить отдельный сервер для example.org":

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

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

HTTPS Solution

Для тех, кто хочет найти решение, включающее https:// ...

server {
        listen 80;
        server_name www.domain.com;
        # $scheme will get the http protocol
        # and 301 is best practice for tablet, phone, desktop and seo
        return 301 $scheme://domain.com$request_uri;
}

server {
        listen 80;
        server_name domain.com;
        # here goes the rest of your config file
        # example 
        location / {

            rewrite ^/cp/login?$ /cp/login.php last;
            # etc etc...

        }
}

Примечание: я изначально не включал https:// в свое решение, так как мы используем loadbalancers и наш сервер https: //сервер платежей SSL с высоким трафиком: мы не смешиваем https: // и http: //.


Чтобы проверить версию nginx, используйте nginx -v.

Удалите www из URL с перенаправлением nginx

server {
    server_name  www.domain.com;
    rewrite ^(.*) http://domain.com$1 permanent;
}

server {
    server_name  domain.com;
    #The rest of your configuration goes here#
}

Таким образом, вам нужно иметь ДВА серверных кода.

Добавьте www вURL с перенаправлением nginx

Если вам нужно обратное, для перенаправления с domain.com на www.domain.com вы можете использовать это:

server {
    server_name  domain.com;
    rewrite ^(.*) http://www.domain.com$1 permanent;
}

server {
    server_name  www.domain.com;
    #The rest of your configuration goes here#
}

КакВы можете себе представить, это как раз наоборот и работает так же, как в первом примере.Таким образом, вы не получите SEO-оценки, так как это перманентное перенаправление и перемещение.Нет WWW принудительно и каталог отображается!

Некоторые из моего кода показаны ниже для лучшего просмотра:

server {
    server_name  www.google.com;
    rewrite ^(.*) http://google.com$1 permanent;
}
server {
       listen 80;
       server_name google.com;
       index index.php index.html;
       ####
       # now pull the site from one directory #
       root /var/www/www.google.com/web;
       # done #
       location = /favicon.ico {
                log_not_found off;
                access_log off;
       }
}
379 голосов
/ 31 июля 2012

На самом деле вам даже не нужно переписывать.

server {
    #listen 80 is default
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

server {
    #listen 80 is default
    server_name example.com;
    ## here goes the rest of your conf...
}

Поскольку мой ответ - это набирать все больше и больше голосов, но и выше.Вы никогда не должны использовать rewrite в этом контексте.Зачем?Потому что nginx должен обработать и начать поиск.Если вы используете return (который должен быть доступен в любой версии nginx), это напрямую останавливает выполнение.Это предпочтительнее в любом контексте.

Перенаправить, не-SSL и SSL, на их не-www аналог:

server {
    listen               80;
    listen               443 ssl;
    server_name          www.example.com;
    ssl_certificate      path/to/cert;
    ssl_certificate_key  path/to/key;

    return 301 $scheme://example.com$request_uri;
}

server {
    listen               80;
    listen               443 ssl;
    server_name          example.com;
    ssl_certificate      path/to/cert;
    ssl_certificate_key  path/to/key;

    # rest goes here...
}

Переменная $scheme будет содержать http только если вашСервер только прослушивает порт 80 (по умолчанию), а опция прослушивания не содержит ключевое слово ssl.Если вы не используете эту переменную, вы не получите никакой производительности.

Обратите внимание, что вам нужно еще больше серверных блоков, если вы используете HSTS, потому что заголовки HSTS не должны отправляться через незашифрованные соединения.Следовательно, вам нужны незашифрованные серверные блоки с перенаправлениями и зашифрованные серверные блоки с перенаправлениями и заголовками HSTS.

Перенаправление всего на SSL (личная конфигурация в UNIX с IPv4, IPv6, SPDY, ...):

#
# Redirect all www to non-www
#
server {
    server_name          www.example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:80;
    listen               *:443 ssl spdy;
    listen               [::]:80 ipv6only=on;
    listen               [::]:443 ssl spdy ipv6only=on;

    return 301 https://example.com$request_uri;
}

#
# Redirect all non-encrypted to encrypted
#
server {
    server_name          example.com;
    listen               *:80;
    listen               [::]:80;

    return 301 https://example.com$request_uri;
}

#
# There we go!
#
server {
    server_name          example.com;
    ssl_certificate      ssl/example.com/crt;
    ssl_certificate_key  ssl/example.com/key;
    listen               *:443 ssl spdy;
    listen               [::]:443 ssl spdy;

    # rest goes here...
}

Полагаю, теперь вы можете сами представить себе другие соединения с этим паттерном.

Больше моих конфигов?Идите сюда и здесь .

34 голосов
/ 14 мая 2015

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

Следующий фрагмент удаляет www перед любым доменом:

if ($host ~* ^www\.(.*)$) {
    rewrite / $scheme://$1 permanent;
}
26 голосов
/ 28 августа 2016

Вам нужно два серверных блока.

Поместите их в свой конфигурационный файл, например /etc/nginx/sites-available/sitename

Допустим, вы решили использовать http://example.com в качестве основного адреса для использования.

Ваш конфигурационный файл должен выглядеть так:

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

        # this is the main server block
        # insert ALL other config or settings in this server block
}

Первый блок сервера будет содержать инструкции по перенаправлению любых запросов с префиксом «www». Он слушает запросы на URL с префиксом «www» и перенаправляет.

Больше ничего не делает.

Второй блок сервера будет содержать ваш основной адрес - URL, который вы хотите использовать. Все остальные настройки идут здесь как root, index, location и т. Д. Проверьте файл по умолчанию для этих других настроек, которые вы можете включить в блок сервера.

Серверу нужны две записи DNS A.

Name: @ IPAddress: your-ip-address (for the example.com URL)

Name: www IPAddress: your-ip-address (for the www.example.com URL)

Для ipv6 создайте пару записей AAAA, используя ваш-ipv6-адрес.

23 голосов
/ 10 декабря 2014

Вот как это сделать для нескольких имен серверов с www на no-www (я использовал это для поддоменов):

server {
        server_name 
             "~^www\.(sub1.example.com)$"
             "~^www\.(sub2.example.com)$"
             "~^www\.(sub3.example.com)$";
         return 301 $scheme://$1$request_uri ;
}
16 голосов
/ 16 октября 2015

Это решение основано на моем личном опыте. Мы использовали несколько корзин Amazon S3 и один сервер для перенаправления доменных имен non-www на www в соответствии с политикой заголовка S3 "Host" .

Я использовал следующую конфигурацию для nginx server:

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

Соответствует всем доменным именам, указанным на сервере, начиная с любого, кроме www., и перенаправляет на www.<domain>. Таким же образом вы можете сделать обратное перенаправление с www на non-www.

14 голосов
/ 25 апреля 2018

Я объединил лучшие из всех простых ответов без жестко закодированных доменов.

301 постоянное перенаправление с не-www на www (HTTP или HTTPS):

server {
    if ($host !~ ^www\.) {
        rewrite ^ $scheme://www.$host$request_uri permanent;
    }

    # Regular location configs...
}

Если вы предпочитаете не HTTPS, не www вместо HTTPS, одновременно перенаправьте www:

server {
    listen 80;

    if ($host !~ ^www\.) {
        rewrite ^ https://www.$host$request_uri permanent;
    }

    rewrite ^ https://$host$request_uri permanent;
}
11 голосов
/ 25 июля 2017

Перенаправление без www на www

Для одного домена:

server {
        server_name example.com;
        return 301 $scheme://www.example.com$request_uri;
}

Для всех доменов:

server {
        server_name "~^(?!www\.).*" ;
        return 301 $scheme://www.$host$request_uri;
}

Перенаправить www на не-www Для одного домена:

server {
        server_name www.example.com;
        return 301 $scheme://example.com$request_uri;
}

Для всех доменов:

server {
         server_name "~^www\.(.*)$" ;
         return 301 $scheme://$1$request_uri ;
}
11 голосов
/ 08 октября 2013

попробуйте это

    if ($host !~* ^www\.){
        rewrite ^(.*)$ https://www.yoursite.com$1;
    }

Другой способ: Nginx без www на www

server {
  listen       80;
  server_name  yoursite.com;
  root /path/;
  index index.php;
  return       301 https://www.yoursite.com$request_uri;
}

и с www на no-www

server {
  listen       80;
  server_name  www.yoursite.com;
  root /path/;
  index index.php;
  return       301 https://yoursite.com$request_uri;
}
9 голосов
/ 23 января 2019
  1. Наилучшая практика: отдельно server с жестким кодом server_name

Наилучшая практика с nginx - использовать отдельную server для перенаправления, подобногоэто (не используется совместно с server вашей основной конфигурации), чтобы жестко закодировать все и вообще не использовать регулярные выражения.

Может также потребоваться жестко закодировать домены, если вы используете HTTPS, потому чтоВы должны заранее знать, какие сертификаты вы будете предоставлять.

server {
    server_name www.example.com;
    return  301 $scheme://example.com$request_uri;
}
server {
    server_name www.example.org;
    return  301 $scheme://example.org$request_uri;
}
server {
    server_name example.com example.org;
    # real configuration goes here
}

Использование регулярных выражений в server_name

Если у вас несколько сайтов, и вам не нужна максимальная производительность, но вы хотите, чтобы каждый из нихчтобы они имели одинаковую политику в отношении префикса www., тогда вы можете использовать регулярные выражения.Лучшая практика использования отдельного server все еще остается в силе.

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


non- www до www с регулярным выражением в выделенном сингле server для всех сайтов:

server {
    server_name ~^(?!www\.)(?<domain>.+)$;
    return  301 $scheme://www.$domain$request_uri;
}

www к не- www с регулярным выражением в выделенном сингле server для всех сайтов:

server {
    server_name ~^www\.(?<domain>.+)$;
    return  301 $scheme://$domain$request_uri;
}

www к не- www с регулярным выражением в выделенном server только для некоторых сайтов:

Может потребоваться ограничить регулярное выражение только несколькими доменами, тогда вы можете использовать что-то подобное, чтобы соответствовать только www.example.org, www.example.com и www.subdomain.example.net:

server {
    server_name ~^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$;
    return  301 $scheme://$domain$request_uri;
}

Проверка регулярных выражений w / nginx

Вы можете проверить, что регулярное выражение работает, как и ожидалось, с pcretest в вашей системе, которая являетсяточно такая же pcre библиотека, которую ваш nginx будет использовать для регулярных выражений:

% pcretest 
PCRE version 8.35 2014-04-04

  re> #^www\.(?<domain>(?:example\.org|example\.com|subdomain\.example\.net))$#
data> test
No match
data> www.example.org
 0: www.example.org
 1: example.org
data> www.test.example.org
No match
data> www.example.com
 0: www.example.com
 1: example.com
data> www.subdomain.example.net
 0: www.subdomain.example.net
 1: subdomain.example.net
data> subdomain.example.net
No match
data> www.subdomain.example.net.
No match
data> 

Обратите внимание, что выне нужно беспокоиться о конечных точках или регистре, поскольку nginx уже позаботился об этом, согласно регулярному выражению имени сервера nginx, когда заголовок "Host" имеет конечную точку .


Sprinkle if в существующих server / HTTPS:

Это окончательное решение, как правило, не считается наилучшей практикой, однако оно все еще работает и работаетзадание.

На самом деле, если вы используете HTTPS, то это окончательное решение может оказаться проще в обслуживании, поскольку вам не придется копировать и вставлять целый набор директив ssl между различными server определений и может вместо этого размещать фрагменты только на нужные серверы, упрощая отладку и поддержку ваших сайтов.


non- www до www:

if ($host ~ ^(?!www\.)(?<domain>.+)$) {
    return  301 $scheme://www.$domain$request_uri;
}

www в non- www:

if ($host ~ ^www\.(?<domain>.+)$) {
    return  301 $scheme://$domain$request_uri;
}

жесткое кодирование одного предпочтительного домена

Если вы хотите немного большей производительности, какКроме согласованности между несколькими доменами, которые может использовать один server, все же может иметь смысл явно жестко кодировать один предпочтительный домен:

if ($host != "example.com") {
    return  301 $scheme://example.com$request_uri;
}

Ссылки:

...