Mummy HTTP and WebSocket Server

repository·master·Indexed 43 days ago

https://github.com/guzba/mummy

A multi-threaded HTTP 1.1 and WebSocket server written in Nim. Mummy uses a worker-thread model instead of async/await, allowing developers to write simple, blocking code for request handlers without stalling the server. It is optimized for memory-light API tasks such as REST, JSON, and RPC.

Tokens
1.2K
Snippets
4
Records
6
Agent score
6%

What's inside Mummy

  1. How Mummy's threading model works

    master

    Mummy uses a hybrid model to maximize performance without the complexity of {.async.}:

    1. Socket IO Thread: A single thread handles all multiplexed socket IO.
    2. Worker Pool: Incoming HTTP requests and WebSocket events are dispatched to a pool of worker threads.

    Key Benefits for Developers:

    • No Async/Await: You do not need to use {.async.}, Future[], or await. Your code remains synchronous and easy to read.
    • Blocking is Safe: Because requests are dispatched to worker threads, you can perform blocking operations (like database queries or file reads) inside your handlers without stalling the entire server.
    • Simpler Error Handling: Use standard try...except blocks. Uncaught exceptions in handlers will not crash the entire server.
    • Thread Safety: Mummy handles the threading and dispatching, so most request handlers do not need to manage threads manually.
  2. Limitations: Large file handling

    master
    Mummy is optimized for memory-light API tasks (REST, JSON, RPC, WebSockets). It is not ideal for serving very large files or handling very large file uploads because it dispatches fully received in-memory requests to worker threads and sends in-memory responses. This can lead to high RAM consumption if the server is not sized appropriately for the expected file sizes.
  3. Configure Nim compiler for Mummy

    master

    Mummy requires specific Nim compiler flags to enable multi-threading and the appropriate memory management. When compiling your project, you must include --threads:on and either --mm:orc or --mm:arc.

    nim c --threads:on --mm:orc your_file.nim
  4. Implement WebSocket support in Mummy

    master

    Mummy provides first-class WebSocket support. To use it:

    1. Define an upgradeHandler that calls request.upgradeToWebSocket().
    2. Define a websocketHandler to process WebSocketEvents (e.g., OpenEvent, MessageEvent, ErrorEvent, CloseEvent).
    3. Pass the websocketHandler to newServer when initializing the server.
    4. Register the upgrade route in your Router.
    import mummy, mummy/routers
    
    proc indexHandler(request: Request) =
      var headers: HttpHeaders
      headers["Content-Type"] = "text/html"
      request.respond(200, headers, """
      <script>
        var ws = new WebSocket("ws://localhost:8080/ws");
        ws.onmessage = function (event) {
          document.body.innerHTML = event.data;
        };
      </script>
      """)
    
    proc upgradeHandler(request: Request) =
      let websocket = request.upgradeToWebSocket()
      websocket.send("Hello world from WebSocket!")
    
    proc websocketHandler(
      websocket: WebSocket,
      event: WebSocketEvent,
      message: Message
    ) =
      case event:
      of OpenEvent:
        discard
      of MessageEvent:
        echo message.kind, ": ", message.data
      of ErrorEvent:
        discard
      of CloseEvent:
        discard
    
    var router: Router
    router.get("/", indexHandler)
    router.get("/ws", upgradeHandler)
    
    let server = newServer(router, websocketHandler)
    echo "Serving on http://localhost:8080"
    server.serve(Port(8080))
  5. Create a basic HTTP server with Mummy

    master

    To create an HTTP server, import mummy and mummy/routers, define a handler that takes a Request and calls request.respond, and then set up a Router to map paths to handlers.

    import mummy, mummy/routers
    
    proc indexHandler(request: Request) =
      var headers: HttpHeaders
      headers["Content-Type"] = "text/plain"
      request.respond(200, headers, "Hello, World!")
    
    var router: Router
    router.get("/", indexHandler)
    
    let server = newServer(router)
    echo "Serving on http://localhost:8080"
    server.serve(Port(8080))