My Falcon based ASGI app is executed via Daphne and works fine when it is run locally and accessed via localhost. The app is packaged in a container and run in a K8s cluster behind an Ingress. On K8s the app is not running at the root of the domain, but in a /sub/folder. This breaks the routing of Falcon. I could not find an existing middleware for this, so I implemented one:
class StripRootPath:
async def process_request(self, req, resp):
root_path = req.root_path
if root_path:
req.path = req.path[len(root_path) :]
This works fine if I call Daphne like this
daphne --root-path /sub/path ...
and as long as I'm only using "normal" HTTP requests. Working with websockets fails. The error messages suggested that paths could not be found, so I assumed that my stripping of the root path did not work. I figured out that I was right. There is a special
async def process_request_ws(self, req, ws):
for websocket connections. I tried to implement this method exactly as process_request but req.root_path is empty. I did not find any value in req that would allow me to strip the prefix.
Now I wonder if I'm doing something completely wrong or if this is a bug and root_path is supposed to be set!?
This seems to be a bug in Daphne, the request scope for WebSocket does not contain the
root_pathkey/value.process_request_wsworked fine to redirect internally by modifyingreq.path, however, I simply hardcoded the prefix in my proof-of-concepttest.py:I tried running the same app in Uvicorn, and
root_pathis present both for ordinaryGETrequests, and when upgraded to a WebSocket:OTOH, even Uvicorn's log illustrates (NB the double
/root/root) the confusion aroundroot_pathin ASGI; contrary to WSGI'sSCRIPT_NAME, it is unclear whether ASGIpathshould include it or not. See also:Despite the confusion, Uvicorn should solve your problem at hand. Moreover, it's one the most popular and performant ASGI app servers out there, so my suggested solution is to simply try swapping out Daphne to Uvicorn.