删除“www”并用nginxredirect到“https”

我想在nginx中创build一个规则来做两件事情:

  1. 删除“www”。 来自请求URI
  2. 如果请求URI是“http”,则redirect到“https

有很多如何做每个单独的事情的例子,但我不能找出一个正确的解决scheme(即不创build一个redirect循环,并正确处理所有情况)。

它需要处理所有这些情况:

1. http://www.example.com/path 2. https://www.example.com/path 3. http://example.com/path 4. https://example.com/path 

这些应该都在https://example.com/path(#4 )没有循环。 有任何想法吗?

    最好的方法是使用三个服务器块:一个redirecthttp到https,一个redirecthttps www-name到no-www,一个实际处理请求。 使用额外的服务器块而不是ifs的原因是服务器select使用散列表执行,而且速度非常快。 如果使用服务器级别,则意味着if会针对每个请求运行,这是浪费的。 而且,在rewrite中捕获请求的uri是浪费的,因为nginx已经在$ uri和$ request_urivariables(分别没有和带有查询string)中具有这个信息。

     server { server_name www.example.com example.com; return 301 https://example.com$request_uri; } server { listen 443 ssl; <possibly other ssl directives if you have a separate cert and key for www> server_name www.example.com; return 301 https://example.com$request_uri; } server { listen 443 ssl; ssl_certificate /path/to/server.cert; ssl_certificate_key /path/to/server.key; server_name example.com; <locations for processing requests> } 

    这适用于我:

     server { listen 80; server_name www.yourdomain.com yourdomain.com; return 301 https://yourdomain.com$request_uri; } server { listen 443 ssl; server_name www.yourdomain.com; ssl_certificate /path/to/certificate.crt; ssl_certificate_key /path/to/private/key.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; return 301 https://yourdomain.com$request_uri; } server { listen 443 ssl; server_name yourdomain.com; ssl_certificate /path/to/certificate.crt; ssl_certificate_key /path/to/private/key.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # do the proper handling of the request } 

    请记住, yourdomain.com www.yourdomain.com 必须位于您的SSL证书中。 这可以通过通配符证书或服务器备用名称来解释。 请查看https://www.startssl.com以获取更好的免费证书&#x3002; ( Edith :从Chrome版本56开始,startssl证书将不再受信任,请尝试https://letsencrypt.org/ )。

    我宁愿返回一个响应代码,以便浏览器知道您将其redirect到另一个URL。

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

    那么https另一个服务器configuration块

     server { listen 443 ssl; server_name example.com; ... } 

    花了这么多时间与数百类似的情况下,我想出了以下片段。 它很短,可以很容易地调整,以适应任何事情。

     server { listen 80; listen 443 ssl; server_name example.com www.example.com; ssl_certificate /path/to/my/certs/example.com/fullchain.pem; ssl_certificate_key /path/to/my/certs/example.com/privkey.pem; # Redirect to the correct place, if needed set $https_redirect 0; if ($server_port = 80) { set $https_redirect 1; } if ($host ~ '^www\.') { set $https_redirect 1; } if ($https_redirect = 1) { return 301 https://example.com$request_uri; } location / { # ... } 

    哦,但if是邪恶的 !

    是的, 可以 。 但这是有原因的,对那些懂得正确使用它的人不应该有任何伤害。 ;)

    如何为此创build一个服务器块:

     server{ listen 80; server_name www.example.net example.net; rewrite ^(.*) https://example.net$1 permanent; } 

    然后重新启动nginx

    我认为这应该工作。

    在你简单的HTTP服务器定义像anthonysomersetbuild议,那就是:

     rewrite ^(.*) https://example.net$1 permanent; 

    然后在你的SSL服务器定义上:

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

    这样,每个请求只能发生一次redirect,无论用户最初使用哪个URL。

    这是完整的例子,最终为我工作。 问题是我没有在wwwredirect块中的ssl细节( ssl_certificate等)。 记得检查你的日志( sudo tail -f /var/log/nginx/error.log )!

     # HTTP — redirect all traffic to HTTPS server { listen 80; listen [::]:80 default_server ipv6only=on; return 301 https://$host$request_uri; } # HTTPS — redirects www to non-www server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.example.com; # Use the Let's Encrypt certificates ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # Include the SSL configuration from cipherli.st include snippets/ssl-params.conf; return 301 https://example.com$request_uri; } # HTTPS — proxy all requests to the app (port 3001) server { # Enable HTTP/2 listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com sub.example.com; # Use the Let's Encrypt certificates ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # Include the SSL configuration from cipherli.st include snippets/ssl-params.conf; # For LetsEncrypt: location ~ /.well-known { root /var/www/html; allow all; } location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-NginX-Proxy true; proxy_pass http://localhost:3001; proxy_ssl_session_reuse off; proxy_set_header Host $http_host; proxy_cache_bypass $http_upgrade; proxy_redirect off; } }