Django 2.0.5升级后Apache+Cherrypy反向代理路径丢失求助
解决反向代理下Django路径前缀丢失的问题
这个问题我太熟悉了!本质是Django没意识到自己是通过/app/这个前缀被反向代理访问的,所以生成URL、处理重定向时都会忽略这个前缀,导致跳转路径出错。开发环境没问题是因为你直接访问Django服务,没有前缀,自然一切正常。下面是一步步的解决办法:
1. 配置Django识别反向代理前缀
首先修改你的Django项目settings.py,添加以下配置:
# 告诉Django应用的根路径前缀 FORCE_SCRIPT_NAME = '/app' # 信任反向代理传递的请求头(Apache会把真实的主机、协议信息放在这些头里) USE_X_FORWARDED_HOST = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # 若使用HTTPS则保留,HTTP环境可删除
FORCE_SCRIPT_NAME是核心配置,它会让Django在生成所有URL时自动带上/app前缀,重定向也会正确包含这个路径。
2. 调整CherryPy的WSGI挂载配置
你的CherryPy脚本里,挂载WSGI应用和静态文件的路径需要和前缀匹配,修改cps.py中的对应部分:
def mount_static(self, url, root): config = { 'tools.staticdir.on': True, 'tools.staticdir.dir': root, 'tools.expires.on': True, 'tools.expires.secs': 86400 } # 静态文件挂载路径要和FORCE_SCRIPT_NAME一致 cherrypy.tree.mount(None, f"{settings.FORCE_SCRIPT_NAME}{settings.STATIC_URL}", {'/': config}) def run(self): cherrypy.config.update({ 'server.socket_host': self.HOST, 'server.socket_port': self.PORT, 'engine.autoreload_on': False, 'log.screen': True, # 开启代理工具,让CherryPy正确处理反向代理请求头 'tools.proxy.on': True }) self.mount_static(settings.STATIC_URL, settings.STATIC_ROOT) cherrypy.log("Load application app") # 将WSGI应用挂载到/app/路径下 cherrypy.tree.graft(WSGIHandler(), settings.FORCE_SCRIPT_NAME) cherrypy.engine.start() cherrypy.engine.block()
主要调整了三个点:
- 静态文件挂载路径加上
/app前缀,确保静态资源URL正确 - 开启CherryPy的
tools.proxy.on,适配反向代理场景 - 将WSGIHandler挂载到
/app/路径,而非根路径
3. 优化Apache反向代理配置
你的Apache配置基础没问题,补充请求头传递并修正代理路径:
<VirtualHost *:*> ServerName example.com ProxyPreserveHost On # 传递真实协议头(HTTPS环境保留) RequestHeader set X-Forwarded-Proto "https" # 代理路径要和Django的FORCE_SCRIPT_NAME匹配 ProxyPass /app/ http://example.com:8000/app/ ProxyPassReverse /app/ http://example.com:8000/app/ </VirtualHost>
让ProxyPass和ProxyPassReverse的目标路径带上/app,确保反向代理传递的请求路径能被CherryPy和Django正确识别。
4. 重启服务测试
最后重启Apache和CherryPy服务验证效果:
# 重启Apache systemctl restart httpd # 重启CherryPy应用(假设用systemd管理) systemctl restart your-app-service
现在访问www.example.com/app,重定向到登录页时应该会正确跳转到www.example.com/app/security/enter,页面跳转也不会再丢失前缀了。
内容的提问来源于stack exchange,提问作者André Thadeu Souza
相关产品推荐
相关产品推荐

