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

K8s Ingress下Falcon+Daphne部署Websocket时root_path为空问题

问题根因

你遇到的是Daphne的已知行为:--root-path参数当前仅会对普通HTTP请求的ASGI scope填充root_path字段,WebSocket握手请求的scope不会自动注入该值,所以Falcon封装的请求对象里req.root_path为空,不属于你代码逻辑的问题,也不是Falcon的系统bug。

可行解决方案

这里提供两种可直接落地的实现方案:

方案1:Ingress透传前缀+中间件适配

首先在K8s Ingress配置中新增规则,给所有转发到该应用的请求添加X-Forwarded-Prefix请求头,值为你的挂载路径/sub/path,之后修改现有中间件兼容WebSocket场景:

class StripRootPath:
    async def process_request(self, req, resp):
        self._strip_prefix(req)

    async def process_request_ws(self, req, ws):
        self._strip_prefix(req)
    
    def _strip_prefix(self, req):
        # 优先取原生root_path,不存在则读取转发头
        root_path = req.root_path or req.get_header('X-Forwarded-Prefix', '')
        if root_path and req.path.startswith(root_path):
            req.path = req.path[len(root_path):]

原有Daphne启动命令保持不变即可。

方案2:外层ASGI中间件统一处理(更稳定)

直接在ASGI应用层统一处理所有请求类型的路径前缀,不需要区分HTTP和WebSocket的逻辑差异,也不依赖Daphne的参数配置:

def add_root_path_middleware(app, root_path):
    async def wrapper(scope, receive, send):
        if scope['type'] in ('http', 'websocket'):
            scope['root_path'] = root_path
            if scope['path'].startswith(root_path):
                scope['path'] = scope['path'][len(root_path):]
        await app(scope, receive, send)
    return wrapper

# 初始化Falcon应用时套上该中间件
import falcon.asgi
app = falcon.asgi.App()
# 替换为你的实际挂载路径
app = add_root_path_middleware(app, root_path='/sub/path')

这种方案适配性更强,后续如果更换ASGI服务器也不需要调整逻辑。

内容的提问来源于stack exchange,提问作者Achim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 17:06:04