Nginx 不會將非 www 重新導向至 www

Nginx 不會將非 www 重新導向至 www

如果使用者在瀏覽器中輸入 example.com,我需要我的 Nginx 設定將使用者重新導向到 www.example.com。原因是我們的 SEO 顧問說應該只有一個首選網域,否則 Google 會將其視為內容重複。反正 。 。 。

所以重點是,我還在伺服器上設定了 Letsencrypt 的 SSL,但我無法實現從 example.com 到 www.example.com 的重定向(伺服器接受這兩個版本)。這是我正在使用的配置:

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

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    server_name example.com www.example.com;
    root /home/my_site;
    index index.php index.html index.htm;

    # for letsencrypt
    location ~ /.well-known {
        allow all;
    }   

    location / { 
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }   

    error_page 404 /404.html;

    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

====更新====

我現在將我的配置更改為蒂姆(我總是這樣nginx -trestart)在以下問題的答案之一中所建議的:

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

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.example.com;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    root /home/ankush/wp_ankushthakur;
    index index.php index.html index.htm;

    # for letsencrypt
    location ~ /.well-known {
        allow all;
    }   

    location / {
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    error_page 404 /404.html;

    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

以下是所有變體的輸出curl -k和存取日誌(我沒有從原始程式碼建立 Nginx,因為我希望有一個更簡單的解決方案並且不想弄亂伺服器):

curl -k http://example.com
Curl output: 301 - Moved permanently
Access logs: "GET / HTTP/1.1" 301 194 "-" "curl/7.47.0"

curl -k http://www.example.com
Curl output: 301 - Moved permanently
Access logs: "GET / HTTP/1.1" 301 194 "-" "curl/7.47.0"

curl -k https://example.com
Curl output: 301 - Moved permanently
Access logs: "GET / HTTP/1.1" 301 194 "-" "curl/7.47.0"

curl -k https://www.example.com
Curl output: <Blank>
Access logs: "GET / HTTP/1.1" 301 5 "-" "curl/7.47.0"

請注意最後一部分,其中 CURL 輸出為空,且存取日誌仍然提供永久重定向。

有趣的是,如果我註解掉第二個server區塊然後重新啟動 Nginx,我最終會得到與我想要的相反的效果:www 重定向到非 www!我對這種情況的發生感到驚訝,因為在這個(第三個)版本的配置中沒有提到 www.example.com 的 HTTPS 版本。

答案1

這可能是因為您僅在 HTTP 上重定向,而不是在 HTTPS 上重定向。您應該將 HTTPS 新增至重定向虛擬主機,並僅保留example.com名稱。

此外,你所做的與人們現在實際做的相反 - 常見的方法是埋葬遺產萬維網舊時代的前綴,只使用簡單的域名,沒有萬維網

答案2

這裡的關鍵是您需要處理四個 URL - www 和非 www 網域的 http 和 https 版本。您的問題是您將 www 和非 www 網域的 http 版本轉發到https://www網域,但您的主伺服器區塊正在監聽這兩個網域https://example.comhttps://www.example.com

您需要做的就是創建一個單獨的伺服器區塊來轉發https://example.comhttps://www.example.com伺服器.您需要在其中包含 https 設定。

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  include snippets/ssl-example.com.conf;
  include snippets/ssl-params.conf;

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

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  include snippets/ssl-example.com.conf;
  include snippets/ssl-params.conf;

  server_name  www.example.com;

  # Main server block for main server continues
}

標準範例

我有教學帶有可下載的設定檔。下面是一個標準範例。

如果這對您不起作用,請使用 -k 選項捲曲每個變體(http 和 https、www 和非 www)以顯示標題並編輯您的問題以包含它們。

# Main server
server {
  server_name www.example.com;
  listen 443 ssl http2;
  # etc, add all locations, call PHP or servers, etc
}


# Forward http requests to https www server
server {
  listen       80;
  server_name  example.com www.example.com;
  return       301 https://www.example.com$request_uri;
}

# Forward https non-www requests to the https www server
# Requires https setup for this server
server {
  listen 443 ssl http2;
  server_name example.com;

  ssl_certificate /var/lib/acme/certs/***CERT_DIRECTORY/fullchain;
  ssl_certificate_key /var/lib/acme/certs/***CERT_DIRECTORY/privkey;

  # Set up preferred protocols and ciphers. TLS1.2 is required for HTTP/2
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;
  ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

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

解決問題 診斷問題的最佳方法是:

  • 在每個域變體上使用“curl -k”(顯示標頭),並結合存取日誌。傳回的 http 狀態代碼會告訴您發生了什麼情況。 200是頁面,301是永久重定向,302是暫時重定向
  • 確保 Nginx 具有 headers_more 模組,您可以透過以下方式執行此操作從原始碼建構 Nginx,這很容易。這允許您將 https 標頭添加到回應中。這是一個很棒的診斷工具。您可以使用這樣的語句來決定正在執行哪些區塊

add_header Z_DEBUG「位置名稱或訊息」;

答案3

我終於能夠說服我們的 SEO 人員將非 www 網域視為主要網域。將 www 重新導向至非 www 的配置如下。儘管我嘗試實現相反的目標有類似的配置,但我不確定是什麼阻止了它。

server {
    listen 80; 
    listen [::]:80;

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

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

    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

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

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

    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    server_name example.com;

    root /home/mysite;
    index index.php;

    location ~ /.well-known {
        allow all;
    }

    location / {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        try_files $uri $uri/ /index.php?$query_string;
        set $path_info $fastcgi_path_info;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
    }
}

相關內容