fasthtml icon indicating copy to clipboard operation
fasthtml copied to clipboard

how to get result from document.addEventListener("keydown")?

Open wcarvalho opened this issue 1 year ago • 3 comments

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?

wcarvalho avatar Aug 03 '24 22:08 wcarvalho

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!

wcarvalho avatar Aug 04 '24 06:08 wcarvalho

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 :-)

psabhay avatar Aug 07 '24 19:08 psabhay

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.

corneliusroemer avatar Aug 15 '24 02:08 corneliusroemer