DigitalOcean上Django+Nginx项目无法将非www域名重定向到www
问题描述
需将https://example.com重定向至https://www.example.com,但当前访问https://example.com会显示Nginx默认欢迎页,www.example.com、admin.example.com、backoffice.example.com均可正常加载。相关配置如下:
Nginx配置(/etc/nginx/sites-available/example)
server { server_name *.example.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { alias /home/admin/pyapps/example/example/static/; } location /static/admin/ { alias /home/admin/pyapps/example/example/static/admin/; } location /media/ { root /home/admin/pyapps/example; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } 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 } server { if ($host = admin.example.com) { return 301 https://$host$request_uri; } # managed by Certbot if ($host = backoffice.example.com) { return 301 https://$host$request_uri; } # managed by Certbot if ($host = www.example.com) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; server_name example.com *.example.com; return 404; # managed by Certbot }
Django-hosts相关配置
settings.py
ROOT_URLCONF = 'example.urls' ROOT_HOSTCONF = 'example.hosts' DEFAULT_HOST = 'www' # DEFAULT_REDIRECT_URL = "http://www.example.com:8000" DEFAULT_REDIRECT_URL = "http://www.example.com" PARENT_HOST = 'example.com' # HOST_PORT = '8000' MIDDLEWARE = [ 'django_hosts.middleware.HostsRequestMiddleware', .... 'django_hosts.middleware.HostsResponseMiddleware', ]
hosts.py
from django.conf import settings from django_hosts import patterns, host from example.hostsconf import urls as redirect_urls from . import admin_urls host_patterns = patterns('', host(r'www', settings.ROOT_URLCONF, name='www'), host(r'admin', admin_urls, name='admin'), host(r'backoffice', 'backoffice.urls', name="backoffice"), host(r'(?!www).*', redirect_urls, name='wildcard'), )
hostsconf/urls.py
from django.urls import path from .views import wildcard_redirect urlpatterns = [ path(r'^?P<path>.*)', wildcard_redirect), ]
hostsconf/views.py
from django.conf import settings from django.http import HttpResponseRedirect DEFAULT_REDIRECT_URL = getattr(settings, "DEFAULT_REDIRECT_URL", "http://www.example.com") def wildcard_redirect(request, path=None): new_url = DEFAULT_REDIRECT_URL if path is not None: new_url = DEFAULT_REDIRECT_URL + '/' + path return HttpResponseRedirect(new_url)
解决方案
1. 修复Nginx配置,让example.com的HTTPS请求进入正确server块
当前443端口的server块server_name仅设置为*.example.com,不匹配无通配符前缀的example.com,导致Nginx用默认server块(显示欢迎页)处理https://example.com请求。修改443 server块的server_name:
server { # 添加example.com,覆盖主域名和所有子域名 server_name example.com *.example.com; # 其余配置保持不变 }
2. 选择重定向实现方式(二选一即可)
方式一:Nginx层面直接重定向(高效推荐)
在443 server块顶部添加重定向规则,优先处理example.com请求:
server { server_name example.com *.example.com; # 匹配主域名,301重定向到www子域名 if ($host = example.com) { return 301 https://www.example.com$request_uri; } # 其余配置保持不变 }
同时修改80端口的server块,添加example.com的HTTP到HTTPS重定向:
server { if ($host = admin.example.com) { return 301 https://$host$request_uri; } # managed by Certbot if ($host = backoffice.example.com) { return 301 https://$host$request_uri; } # managed by Certbot if ($host = www.example.com) { return 301 https://$host$request_uri; } # managed by Certbot # 添加主域名HTTP请求的重定向规则 if ($host = example.com) { return 301 https://www.example.com$request_uri; } listen 80; server_name example.com *.example.com; return 404; # managed by Certbot }
方式二:修复Django-hosts配置,由Django处理重定向
调整hosts.py的主机匹配规则
当前(?!www).*正则无法匹配空前缀(即example.com本身),需添加专门的主域名匹配规则:
host_patterns = patterns('', host(r'www', settings.ROOT_URLCONF, name='www'), host(r'admin', admin_urls, name='admin'), host(r'backoffice', 'backoffice.urls', name="backoffice"), # 匹配无前缀的主域名 host(r'', redirect_urls, name='root'), # 保留原有规则处理其他子域名 host(r'(?!www).*', redirect_urls, name='wildcard'), )
修复hostsconf/urls.py的路径匹配语法错误
path不支持正则捕获组,需改用re_path:
from django.urls import re_path from .views import wildcard_redirect urlpatterns = [ re_path(r'^(?P<path>.*)', wildcard_redirect), ]
更新重定向URL为HTTPS
修改hostsconf/views.py和settings.py中的重定向地址:
# hostsconf/views.py DEFAULT_REDIRECT_URL = getattr(settings, "DEFAULT_REDIRECT_URL", "https://www.example.com") # settings.py DEFAULT_REDIRECT_URL = "https://www.example.com"
3. 验证配置并重启服务
检查Nginx配置正确性:
sudo nginx -t
无错误则重启Nginx:
sudo systemctl restart nginx
若使用方式二,同时重启Gunicorn:
sudo systemctl restart gunicorn
内容的提问来源于stack exchange,提问作者pH4nT0M
相关产品推荐
相关产品推荐

