fasthtml
fasthtml copied to clipboard
how to get result from document.addEventListener("keydown")?
I want to have python functions which respond to different key presses. I'm trying to add an event listener but I can't figure out how to route it to a python function. This is what I have so far...
python:
from fasthtml.common import *
secret_key = "your-secret-key-here"
app = FastHTML(
ws_hdr=True,
middleware=[
Middleware(SessionMiddleware, secret_key=secret_key)
],
)
async def on_connect(self, send):
pass
async def on_disconnect(self):
pass
@app.ws('/ws', conn=on_connect, disconn=on_disconnect)
async def ws(msg: str, send):
print(msg)
@app.route("/")
async def get(request: Request):
return Div(
Script("""
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const host = window.location.host;
const wsUrl = `${protocol}//${host}/ws`;
const socket = new WebSocket(wsUrl);
console.log('socket created');
document.addEventListener("keydown", function(event) {
console.log(event.key);
socket.send(JSON.stringify({key: event.key}));
});
""")
)
I get the following error:
Traceback (most recent call last):
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 244, in run_asgi
result = await self.app(self.scope, self.asgi_receive, self.asgi_send) # type: ignore[func-returns-value]
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__
return await self.app(scope, receive, send)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/applications.py", line 123, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/middleware/errors.py", line 151, in __call__
await self.app(scope, receive, send)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/middleware/sessions.py", line 85, in __call__
await self.app(scope, receive, send_wrapper)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/middleware/sessions.py", line 85, in __call__
await self.app(scope, receive, send_wrapper)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 65, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
raise exc
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
await app(scope, receive, sender)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/routing.py", line 756, in __call__
await self.middleware_stack(scope, receive, send)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/routing.py", line 776, in app
await route.handle(scope, receive, send)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/routing.py", line 373, in handle
await self.app(scope, receive, send)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/endpoints.py", line 90, in dispatch
raise exc
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/starlette/endpoints.py", line 82, in dispatch
await self.on_receive(websocket, data)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/fasthtml/core.py", line 237, in _recv
async def _recv(self, ws, data): await _generic_handler(recv, ws, data)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/fasthtml/core.py", line 227, in _generic_handler
wd = _wrap_ws(ws, loads(data) if data else {}, signature(handler).parameters)
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/fasthtml/core.py", line 215, in _wrap_ws
return [_find_wsp(ws, data, hdrs, arg, p) for arg,p in params.items()]
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/fasthtml/core.py", line 215, in <listcomp>
return [_find_wsp(ws, data, hdrs, arg, p) for arg,p in params.items()]
File "/Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/fasthtml/core.py", line 206, in _find_wsp
if res is empty or res is None: res = headers.get(snake2hyphens(arg), None)
NameError: name 'headers' is not defined. Did you mean: 'Header'?
am I doing something wrong or is this a bug in the library?
To give some context, I'm trying to build an interactive game web app with fasthtml where a user plays a game with a keyboard. e.g. up arrow leads them to control an avatar which goes up 1 tile. is there an easy way to (a) create a websocket for more real-time-y game-play (b) get the key the user pressed and (c) send back updated html?
Maybe I'm going about this incorrectly. Please feel free to suggest another solution. thank you!
I think there is a problem in line 206 of /Users/wilka/miniforge3/envs/web-dev/lib/python3.10/site-packages/fasthtml/core.py. The headers are in the request object in other cases. I think in case of WS and inside this function the headers are passed as hdrs so the code at line 206 should look like this - if res is empty or res is None: res = hdrs.get(snake2hyphens(arg), None). But I can't test it and verify right now. Try changing the code at your end and see if that works :-)
Later may be create a PR with all the details so that someone could review it :-)
It might be good to turn this into a more focused bug report, solely about the Middleware error.
The rest of the question might be best suited for Stackoverflow
Lastly, if you add py after your triple back ticks, GitHub syntax highlights, which helps readers.