Nginx非www转www重定向对子目录失效,求问题原因分析
问题原因分析
你的问题出在HTTPS请求的处理逻辑上:第一个server块同时监听了example.com和www.example.com的443端口请求,所以当用户访问https://example.com/es/这类非www的HTTPS子目录时,请求直接匹配到这个server块里的location /规则,被代理到Gunicorn,完全没触发重定向逻辑。而第二个server块只负责处理80端口的HTTP请求,所以只有HTTP的首页和子目录会被重定向,HTTPS的非www请求根本没走到重定向步骤。
修正后的配置方案
你需要把HTTPS的server块拆分成两个:一个专门处理example.com的HTTPS请求并做重定向,另一个处理www.example.com的HTTPS请求并处理业务逻辑。修改后的完整配置如下:
# 处理非www的HTTPS请求,直接重定向到www版本 server { server_name example.com; listen 443 ssl; # managed by Certbot 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 include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot # 所有请求都重定向到www.example.com,保留完整请求路径 return 301 https://www.example.com$request_uri; } # 处理www的HTTPS请求,负责业务逻辑 server { server_name www.example.com; listen 443 ssl; # managed by Certbot 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 include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot location = /favicon.ico { access_log off; log_not_found off; } location /core/static { alias /home/andrea/agency/core/static/; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } } # 处理HTTP请求,统一重定向到HTTPS的www版本 server { listen 80; server_name example.com www.example.com; if ($host = example.com) { return 301 https://www.example.com$request_uri; } if ($host = www.example.com) { return 301 https://$host$request_uri; } return 404; # managed by Certbot }
关键改动说明
- 拆分了HTTPS的server块:现在
example.com的HTTPS请求会被单独捕获,直接返回301重定向,确保所有非www的HTTPS请求(包括子目录)都能跳转到对应的www路径。 - 保留了
$request_uri:这个变量确实会完整保留请求的路径和参数,所以重定向后example.com/es/会正确跳转到www.example.com/es/。 - 原有的业务逻辑(静态文件、Gunicorn代理)只保留在
www.example.com的server块中,避免冲突。
修改完成后,记得重启Nginx生效:
sudo systemctl restart nginx
内容的提问来源于stack exchange,提问作者Askew
相关产品推荐
相关产品推荐

