Flask子域名路由需开启SERVER_NAME并正确配置端口,使用Blueprint的subdomain参数定义路由,通过before_request处理无子域名请求,并确保反向代理透传Host头。

子域名路由必须开启SERVER_NAME且配置正确
Flask默认不解析子域名,SERVER_NAME 是启用子域名匹配的开关。它不仅要设值,还必须包含端口(即使80/443)——否则request.host与路由比对会失败。本地开发时常见填 "localhost:5000",但浏览器访问 user.localhost:5000 仍可能被拒绝,因为部分系统不支持带点的 localhost 解析;更稳妥的是改用 lvh.me(自动解析到127.0.0.1)并设 SERVER_NAME="lvh.me:5000"。
用subdomain参数定义蓝图路由
单靠@app.route无法绑定子域名,必须用蓝图(Blueprint)配合subdomain参数。每个子域名对应一个独立蓝图,注册时指定subdomain,例如:
admin_bp = Blueprint('admin', __name__, subdomain='admin')
user_bp = Blueprint('user', __name__, subdomain='user')
@app.before_request
def ensure_subdomain():
if not request.subdomain:
return redirect(f'www.{request.host}', 302)
admin_bp.route('/dashboard')(lambda: 'Admin dashboard')
user_bp.route('/profile')(lambda: 'User profile')
app.register_blueprint(admin_bp)
app.register_blueprint(user_bp)
注意:request.subdomain 是 Flask 自动提取的字段,依赖 SERVER_NAME 正确设置;若未匹配到任何subdomain蓝图,请求会落到全局路由或返回404。
处理无子域名或www的兜底逻辑
用户直接访问 example.com 或 www.example.com 时,request.subdomain 为空字符串,不会命中任何subdomain蓝图。不能靠“默认蓝图”解决,必须显式拦截:
- 用
@app.before_request检查request.subdomain是否为空,再根据request.host做重定向或渲染主页 - 避免在根蓝图里写
@app.route('/', subdomain='—— Flask 不支持通配符子域名') - 若需支持
www,得单独注册一个subdomain='www'的蓝图,或在 before_request 中统一处理
反向代理下HOST头可能被污染
部署到 Nginx/Gunicorn 时,真实 Host 头常被代理覆盖。Flask 读取的是 WSGI 环境中的 HTTP_HOST,若 Nginx 没透传原始 Host,request.host 和 request.subdomain 就会错乱。必须确保 Nginx 配置含:
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://flask_app;
}
同时 Flask 需启用信任代理:设 app.config['PREFERRED_URL_SCHEME'] = 'https'(如用 HTTPS),并确认 request.host 解析逻辑没被 X-Forwarded-Host 干扰——Flask 默认不读该头,除非手动集成中间件。
子域名分发真正的难点不在路由注册,而在于环境一致性:开发时的 DNS 解析、测试时的 Hosts 修改、生产时的反向代理头透传,三者只要一环脱节,request.subdomain 就是空的——这时候所有子域名路由都静默失效,连日志都不报错。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











