cirospaciari / socketify.py

Bringing Http/Https and WebSockets High Performance servers for PyPy3 and Python3
https://www.socketify.dev
MIT License
1.38k stars 48 forks source link

Add more developer-friendly WebSocket Interface #57

Open VincentRPS opened 1 year ago

VincentRPS commented 1 year ago

Is your feature request related to a problem? Please describe.

Currently, Socketify uses a method of using the open, message, and close indicators to show parse the obvious. This makes it much harder to track and sustain a connection easily.

Describe the solution you'd like

I would like an implementation to something like what the WebSockets library has, and what most other libraries do:

async def websocket_handler(ws: socketify.WebSocket) -> None:
    await user_online()

    # stops looping on close
    async for msg in ws:
       await ws.send('hey!')

    await user_offline()

app.ws('/websocket', {
    'compression': CompressOptions.SHARED_COMPRESSOR,
    'max_payload_length': 16 * 1024 * 1024,
    'idle_timeout': 12,
    'handler': websocket_handler,
    'drain': lambda ws: print('WebSocket backpressure: %i' % ws.get_buffered_amount()),
})

This would be optional, and not required to use websockets. It'd also make it much easier to keep state if, per se, you're trying to make a chat app or another similar thing which requires state and easy DX.

else then all of that though, I'd just like to say that this project is really nice, I've always been looking for a fast Python websocket lib and I think this one is a first, I can't wait to see this library be production-ready!

cirospaciari commented 1 year ago

The current version basically is a 1-to-1 representation of uWS C++ WS, I will not change this, but I can add some helpers, adding an async/ASGI-like wrapper will add a ton of overhead, and socketify.py focus is performance. But I will consider adding an official helper.

cirospaciari commented 1 year ago

I will add better DX in WebSockets after this features:

  1. Better routers https://github.com/cirospaciari/socketify.py/issues/59
  2. Hot reloading https://github.com/cirospaciari/socketify.py/issues/61
  3. Plugins / Extensions https://github.com/cirospaciari/socketify.py/issues/62
  4. on_start, on_shutdown hooks https://github.com/cirospaciari/socketify.py/issues/58
  5. Cache tools https://github.com/cirospaciari/socketify.py/issues/60
  6. Native optimizations https://github.com/cirospaciari/socketify.py/issues/52

Will be better, in general, using decorators or something similar to handle the websocket events and routes.

from socketify import App

app = App()
ws = app.ws("/websocket",  {
    'compression': CompressOptions.SHARED_COMPRESSOR,
    'max_payload_length': 16 * 1024 * 1024,
    'idle_timeout': 12,
})
@ws.open
def ws_open(ws):
    print("A WebSocket got connected!")
    ws.send("Hello World!", OpCode.TEXT)

@ws.message
def ws_message(ws, message, opcode):
    print(message, opcode)
    # Ok is false if backpressure was built up, wait for drain
    ok = ws.send(message, opcode)

@ws.close
def ws_message( ws, code, message):
     print("WebSocket closed")

I will also add a decorator for something similar to what you proposed too, something similar to ASGI form of handling connections, will be overhead and I will measure it and add it to the docs and the user can decide if is worth it or not.

Edit: almost there!