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
相关产品推荐
相关产品推荐

