这似乎是 Daphne 的一个错误,WebSocket 的请求范围不包含 root_path 键/值。
process_request_ws 通过修改req.path 可以很好地在内部重定向,但是,我只是在我的概念验证test.py 中硬编码了前缀:
import falcon
import falcon.asgi
class InternalRedirect:
async def process_request(self, req, resp):
print(f'req.path={req.path}; req.root_path={req.root_path}')
if req.path.startswith('/root/'):
req.path = req.path.split('/root', 1)[1]
async def process_request_ws(self, req, ws):
print(f'req.path={req.path}; req.root_path={req.root_path}')
if req.path.startswith('/root/'):
req.path = req.path.split('/root', 1)[1]
class HelloResource:
async def on_get(self, req, resp, name):
resp.media = {'message': f'Hello, {name}!'}
async def on_websocket(self, req, ws, name):
try:
await ws.accept()
await ws.send_media({'message': f'Hello, {name}'})
while True:
payload = await ws.receive_text()
print(f'Received: [{payload}])')
except falcon.WebSocketDisconnected:
pass
app = falcon.asgi.App(middleware=[InternalRedirect()])
app.add_route('/hello/{name}', HelloResource())
我尝试在Uvicorn 中运行相同的应用程序,而root_path 既适用于普通的GET 请求,也适用于升级到WebSocket:
$ uvicorn --root-path /root test:app
...
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
req.path=/root/hello/robot; req.root_path=/root
INFO: ('127.0.0.1', 33776) - "WebSocket /root/root/hello/robot" [accepted]
INFO: connection open
INFO: connection closed
OTOH,甚至 Uvicorn 的日志也说明了(注意双重 /root/root)在 ASGI 中围绕 root_path 的混乱;与 WSGI 的 SCRIPT_NAME 相反,尚不清楚 ASGI path 是否应该包含它。
另见:
尽管存在混乱,Uvicorn 应该可以解决您手头的问题。此外,它是目前最受欢迎和性能最好的 ASGI 应用服务器之一,所以我建议的解决方案是尝试将 Daphne 换成 Uvicorn。