Nginx非WWW转WWW配置异常:浏览器反向跳转、Curl返回200
咱们先拆解你的配置和现象里的矛盾点,一步步找到问题根源:
1. Nginx HTTP 配置的顺序逻辑错误
你的HTTP部分有两个server块,但第一个listen 80 default_server的块会拦截所有80端口的请求(不管域名是example.com还是www.example.com),直接跳转到https://$host$request_uri。这就导致第二个server_name example.com的块完全不会被触发——所有HTTP请求都走了第一个默认server,所以http://example.com只会被跳转到https://example.com,而不是你期望的https://www.example.com。
2. HTTPS 缺少example.com的专属处理块
你的HTTPS配置只有server_name www.example.com的代理块,没有针对example.comHTTPS请求的规则。当用户访问https://example.com时,Nginx找不到匹配的server块,就会自动用第一个监听443端口的server块(也就是www的那个)来处理请求,直接把流量转发给Node应用。
这时候curl请求会返回200(因为curl默认不缓存重定向),但浏览器可能缓存了之前的301重定向规则(比如你之前可能配置过www→非www的永久重定向,而301会被浏览器强制缓存),就出现了浏览器反向跳转的异常。
3. 浏览器缓存的301重定向是直接诱因
301永久重定向的缓存优先级很高,哪怕你现在改了Nginx配置,浏览器依然会沿用旧的重定向逻辑。这就是为什么终端curl请求显示正常,但浏览器访问时出现反向跳转的核心原因。
第一步:修正HTTP重定向配置
把HTTP部分的两个server块合并,确保所有HTTP请求直接跳转到HTTPS的www域名:
# HTTP — redirect all traffic to HTTPS WWW server { listen 80; listen [::]:80 default_server ipv6only=on; server_name example.com www.example.com; return 301 https://www.example.com$request_uri; }
第二步:添加HTTPS的example.com重定向块
在现有HTTPS代理块之前,添加专门处理example.comHTTPS请求的规则:
# HTTPS — redirect non-WWW to WWW server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot ssl_dhparam /etc/ssl/certs/dhparam.pem; # include snippets/ssl-params.conf; return 301 https://www.example.com$request_uri; } # 原有的HTTPS代理server块保持不变 server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name www.example.com; # ... 其余代理配置不变 }
第三步:规避浏览器缓存干扰
修改配置后,需要:
- 清除浏览器的缓存(重点清除缓存的重定向规则)
- 或者直接用隐私/无痕模式访问,避免旧缓存影响测试
第四步:重启Nginx生效
执行命令让新配置生效:
sudo systemctl restart nginx
这样配置后,所有HTTP/HTTPS的非www请求都会被正确跳转到www,同时解决了浏览器缓存导致的异常问题。
内容的提问来源于stack exchange,提问作者lightbringer




