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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:57:03