You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 08:20:12