web-dev-qa-db-fra.com

Nginx no-www to www et www to no-www

J'utilise nginx sur le cloud Rackspace à la suite d'un tutoriel et après une recherche sur le net, je ne parviens pas à résoudre ce problème.

Je veux que www.monsite.com aille sur mysite.com comme d'habitude dans .htaccess pour le référencement et d'autres raisons.

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

J'ai aussi essayé

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

J'ai aussi essayé. La deuxième tentative donne des erreurs de boucle de redirection.

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

Mon DNS est configuré en standard:

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

(Des exemples d'adresses IP et de dossiers ont été utilisés pour des exemples et pour aider des personnes à l'avenir). J'utilise Ubuntu 11.

450
TheBlackBenzKid

Solution HTTP

A partir de la documentation , "le bon moyen est de définir un serveur séparé pour 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;
    ...
}

Solution HTTPS

Pour ceux qui veulent une solution incluant 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...

        }
}

Remarque: à l'origine, je n'ai pas inclus https:// dans ma solution, car nous utilisons des loadbalancers et notre serveur https: // est un serveur de paiement SSL à trafic élevé: nous ne mélangeons pas https: // et http: //.


Pour vérifier la version de nginx, utilisez nginx -v

Strip www à partir de l'URL avec la redirection 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#
}

Donc, vous devez avoir deux codes de serveur.

Ajouter le www à l'URL avec la redirection nginx

Si vous avez besoin du contraire, pour rediriger de domain.com vers www.domain.com, vous pouvez utiliser ceci:

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

Comme vous pouvez l’imaginer, c’est tout le contraire qui se produit et fonctionne de la même manière que le premier exemple. De cette façon, vous n'obtiendrez pas les marques de référencement, car il s'agit d'une redirection et d'un déplacement permanents de la perm. Le non WWW est forcé et le répertoire affiché!

Certains de mes codes ci-dessous pour une meilleure vue:

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

En fait, vous n'avez même pas besoin d'une réécriture.

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

Comme ma réponse est de plus en plus de votes mais le ci-dessus aussi. Vous ne devriez jamais utiliser une rewrite dans ce contexte. Pourquoi? Parce que nginx doit traiter et lancer une recherche. Si vous utilisez return (qui devrait être disponible dans n'importe quelle version de nginx), l'exécution s'arrête directement. Ceci est préféré dans n'importe quel contexte.

Rediriger les deux, non SSL et SSL vers leur homologue non-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...
}

La variable $scheme ne contiendra que http si votre serveur n'écoute que sur le port 80 (valeur par défaut) et que l'option d'écoute ne contient pas le mot clé ssl. Ne pas utiliser la variable ne vous rapportera aucune performance.

Notez que vous avez besoin de davantage de blocs serveur si vous utilisez HSTS, car les en-têtes HSTS ne doivent pas être envoyés via des connexions non chiffrées. Par conséquent, vous avez besoin de blocs de serveur non chiffrés avec des redirections et de blocs de serveur chiffrés avec des redirections et des en-têtes HSTS.

Tout rediriger vers SSL (configuration personnelle sous UNIX avec 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...
}

Je suppose que vous pouvez imaginer d’autres composés avec ce motif maintenant par vous-même.

Plus de mes configs? Allez ici et ici .

371
Fleshgrinder

Vous découvrirez peut-être que vous souhaitez utiliser la même configuration pour plusieurs domaines.

L'extrait suivant supprime www avant tout domaine:

if ($Host ~* ^www\.(.*)$) {
    rewrite / $scheme://$1 permanent;
}
30
Martin Höger

Vous avez besoin de deux blocs de serveur. 

Mettez-les dans votre fichier de configuration, par exemple /etc/nginx/sites-available/sitename

Supposons que vous décidiez d'avoir http://example.com comme adresse principale à utiliser.

Votre fichier de configuration devrait ressembler à ceci:

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
}

Le premier bloc de serveur contiendra les instructions pour rediriger les requêtes avec le préfixe 'www'. Il écoute les requêtes pour l'URL avec le préfixe 'www' et les redirections. 

Cela ne fait rien d'autre.

Le deuxième bloc de serveur contiendra votre adresse principale - l'URL que vous souhaitez utiliser. Tous les autres paramètres vont ici comme root, index, location, etc. Vérifiez le fichier par défaut pour ces autres paramètres que vous pouvez inclure dans le bloc serveur.

Le serveur a besoin de deux enregistrements DNS A.

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

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

Pour ipv6, créez la paire d’enregistrements AAAA en utilisant votre-adresse-ipv6.

26
Red

Voici comment le faire pour plusieurs noms de serveur www à no-www (je l'ai utilisé pour les sous-domaines):

server {
        server_name 
             "~^www\.(sub1.example.com)$"
             "~^www\.(sub2.example.com)$"
             "~^www\.(sub3.example.com)$";
         return 301 $scheme://$1$request_uri ;
}
22
Eric Johnson

Cette solution vient de mon expérience personnelle. Nous avons utilisé plusieurs compartiments Amazon S3 et un serveur pour rediriger les noms de domaine non-www vers www afin qu'ils correspondent à stratégie d'en-tête "hôte" S3 }.

J'ai utilisé la configuration suivante pour le serveur nginx:

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

Cela correspond à tous les noms de domaine pointés vers le serveur commençant par un nom quelconque sauf www. et redirigeant vers www.<domain>. De la même manière, vous pouvez faire la réversion opposée de www à non-www.

16
VisioN

J'ai combiné le meilleur de toutes les réponses simples, sans domaines codés en dur.

301 redirection permanente de non-www vers www (HTTP ou HTTPS):

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

    # Regular location configs...
}

Si vous préférez les protocoles non-HTTPS, non-www à HTTPS, redirigez simultanément www:

server {
    listen 80;

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

    rewrite ^ https://$Host$request_uri permanent;
}
13
Matt Janssen

essaye ça

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

Autre moyen: Nginx no-www to www

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

et www à no-www

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

Rediriger les non-www vers www

Pour un domaine unique: 

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

Pour tous les domaines: 

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

Rediriger www vers non-www Pour un domaine unique:

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

Pour tous les domaines:

server {
         server_name "~^www\.(.*)$" ;
         return 301 $scheme://$1$request_uri ;
}
8
Ravindra Bhalothia

Format unique:

server {
  listen 80;
  server_name "~^www\.(.*)$" ;
  return 301 https://$1$request_uri ;
}
7
Andriyun
location / { 
    if ($http_Host !~ "^www.domain.com"){ 
        rewrite ^(.*)$ $scheme://www.domain.com/$1 redirect; 
    } 
}
4
Maoz Zadok

je ne sais pas si quelqu'un remarquera qu'il est peut-être correct de renvoyer un 301, mais les navigateurs s'y étouffent.

rewrite ^(.*)$ https://yoursite.com$1; 

est plus rapide que:

return 301 $scheme://yoursite.com$request_uri;
3
steven
  1. Meilleure pratique: séparer server avec __codé server_name

La meilleure pratique avec nginx est d’utiliser une variable server distincte pour une redirection comme celle-ci (non partagée avec la variable server de votre configuration principale), de coder en dur tout et de ne pas utiliser d’expressions régulières.

Si vous utilisez HTTPS, il peut également être nécessaire de coder en dur les domaines, car vous devez savoir à l’avance quels certificats vous allez fournir.

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
}

  1. Utilisation d'expressions régulières dans server_name

Si vous avez plusieurs sites et que vous n'aimez pas les performances les plus élevées, mais que vous souhaitez que chacun d'entre eux applique la même stratégie en ce qui concerne le préfixe www., vous pouvez utiliser des expressions régulières. La meilleure pratique consistant à utiliser une server distincte serait toujours valable.

Notez que cette solution devient délicate si vous utilisez https, car vous devez disposer d'un seul certificat pour couvrir tous vos noms de domaine si vous souhaitez que cela fonctionne correctement.


non -www à www avec regex dans un unique server dédié pour tous les sites:

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

www à non -www avec regex dans un unique server dédié pour tous les sites:

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

www à non -www avec regex dans un server dédié pour certains sites uniquement:

Il peut être nécessaire de restreindre l’expression rationnelle de manière à ne couvrir que quelques domaines. Vous pouvez ensuite utiliser ce type de méthode pour ne faire correspondre que www.example.org, www.example.com et www.subdomain.example.net:

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

Test des expressions régulières avec nginx

Vous pouvez vérifier que l'expression rationnelle fonctionne comme prévu avec pcretest sur votre système, ce qui correspond exactement à la même bibliothèque pcre que votre nginx utilisera pour les expressions régulières:

% 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> 

Notez que vous n'avez pas à vous soucier des points ou des cas de fin, car nginx s'en occupe déjà, comme indiqué dans nginx nom de serveur regex lorsque l'en-tête "Host" a un point de fin .


  1. Saupoudrer if dans server/HTTPS existant:

Cette solution finale n'est généralement pas considérée comme la meilleure pratique, mais elle fonctionne toujours et fonctionne bien.

En fait, si vous utilisez HTTPS, cette solution finale risque d’être plus facile à gérer, car vous n’auriez pas à copier-coller tout un ensemble de directives ssl entre les différentes définitions server et à placer à la place les extraits uniquement. dans les serveurs nécessaires, ce qui facilite le débogage et la maintenance de vos sites.


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

coder en dur un seul domaine préféré

Si vous voulez un peu plus de performances, ainsi que de cohérence entre plusieurs domaines qu’une seule server peut utiliser, il pourrait toujours être judicieux de coder explicitement un domaine unique:

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

Références:

2
cnst

Blog fantôme

pour que la méthode recommandée avec return 301 $scheme://example.com$request_uri; par nginx fonctionne avec Ghost, vous devez ajouter le bloc de votre serveur principal:

proxy_set_header    X-Real-IP           $remote_addr;
proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
proxy_set_header    Host                $http_Host;
proxy_set_header    X-Forwarded-Proto   $scheme;
proxy_set_header    X-NginX-Proxy       true;

proxy_pass_header   X-CSRF-TOKEN;
proxy_buffering     off;
proxy_redirect      off;  
2
nottinhill
if ($Host ~* ^www.example.com$) {
    return 301 $scheme://example.com$request_uri;
}
0
karadayi

Si vous ne voulez pas coder en dur le nom de domaine, vous pouvez utiliser ce bloc de redirection. Le domaine sans le www principal est enregistré en tant que variable $domain qui peut être réutilisé dans l'instruction de redirection.

server {
    ...
    # Redirect www to non-www
    if ( $Host ~ ^www\.(?<domain>.+) ) {
       rewrite ^/(.*)$ $scheme://$domain/$1;
    }
}

REF: Redirection d'un sous-domaine avec une expression rationnelle dans nginx

0
Drakes