當前位置: 首頁>>技術教程>>正文


redirect – Nginx no-www到www以及www到no-www

, , , ,

問題描述

我正在使用nginx on Rackspace cloud following a tutorial並已搜索過網絡,到目前為止無法進行排序。

由於SEO和其他原因,我希望www.mysite.com可以正常訪問.htaccess中的mysite.com。

我的/etc/nginx/sites-available/www.example.com.vhost配置:

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。

最佳方法

HTTP解決方案

documentation中,“正確的方法是為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解決方案

對於那些想要包括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://服務器是high-traffic SSL付款服務器,因此我最初沒有在解決方案中包含https://:我們不混合使用https://和http://。


要檢查nginx版本,請使用nginx -v

使用nginx重定向從URL中刪除www

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

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

因此,您需要兩個服務器代碼。

使用Nginx重定向將www添加到URL

如果您需要的是相反的方法,則要從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;
       }
}

次佳方法

實際上,您甚至不需要重寫。

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

如果服務器僅在端口80上偵聽(默認),並且偵聽選項不包含ssl關鍵字,則$scheme變量將僅包含http。不使用該變量將不會獲得任何性能。

請注意,如果使用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...
}

我想您現在可以自己想象具有這種模式的其他化合物。

更多我的配置?轉到herehere

第三種方法

您可能會發現要對更多域使用相同的配置。

以下代碼段會在任何域之前刪除www:

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

第四種方法

您需要兩個服務器塊。

將它們放入您的配置文件中,例如/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’前綴重定向任何請求。它偵聽帶有’www’前綴的URL請求並重定向。

它什麽也沒做。

第二個服務器塊將保留您的主要地址,即您要使用的URL。其他所有設置都在這裏,例如rootindexlocation等。請檢查默認文件以獲取可包含在服務器塊中的這些其他設置。

服務器需要兩個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,請使用your-ipv6-address創建AAAA記錄對。

第五種方法

這是將多個www轉換為no-www服務器名稱的方法(我將其用於子域):

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

第六種方法

此解決方案來自我的個人經驗。我們使用了幾個Amazon S3存儲桶和一個服務器將non-www重定向到www域名以匹配S3 “Host” header policy

我對nginx服務器使用了以下配置:

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

這匹配指向除www.以外的所有指向服務器的域名,並重定向到www.<domain>。以相同的方式,您可以執行從wwwnon-www的反向重定向。

第七種方法

在沒有hard-coded域的情況下,我結合了所有簡單答案中的最佳方法。

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

第八種方法

  1. 最佳實踐:帶硬編碼的server_name的單獨server

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
}

  1. server_name中使用正則表達式

如果您有多個站點,並且不希望獲得最高的性能,但是希望每個站點在www.前綴方麵都具有相同的策略,則可以使用正則表達式。使用單獨的server的最佳實踐仍然有效。

請注意,如果您使用https,則此解決方案會很棘手,因為如果您希望此方法正常運行,則必須具有一個證書來覆蓋所有域名。


適用於所有站點的專用單個server中的非www到正則表達式的www

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

適用於所有站點的專用單個server中的www到帶有正則表達式的非www

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

www到帶有正則表達式的非www(專用於某些站點)在專用server中:

可能有必要將正則表達式限製為僅覆蓋兩個域,然後可以使用類似這樣的方法來僅匹配www.example.orgwww.example.comwww.subdomain.example.net

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

使用nginx測試正則表達式

您可以測試正則表達式與係統上的pcretest是否可以正常工作,這與您的nginx用於正則表達式的pcre庫完全相同:

% 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 server name regex when “Host” header has a trailing dot,您不必擔心尾隨點或大小寫,因為nginx已經處理了它。


  1. if撒在現有的server /HTTPS中:

最終解決方案通常不被視為最佳實踐,但是,它仍然可以正常工作。

實際上,如果您使用的是HTTPS,則最終的解決方案可能最終更易於維護,因為您不必在不同的server定義之間使用copy-paste一大堆ssl指令,而隻需將代碼段放入所需的服務器,從而使調試和維護站點變得更加容易。


wwwwww

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

www到非www

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

硬編碼單個首選域

如果您希望獲得更高的性能以及單個server可以使用的多個域之間的一致性,那麽顯式地對單個首選域進行硬編碼仍然有意義:

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

參考文獻:

第九種方法

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

第十種方法

嘗試這個

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

其他方式:Nginx no-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;
}

參考資料

本文由Ubuntu問答整理, 博文地址: https://ubuntuqa.com/zh-tw/article/8455.html,未經允許,請勿轉載。