server

Example

import websocket, asynchttpserver, asyncnet, asyncdispatch

let server = newAsyncHttpServer()

proc cb(req: Request) {.async.} =
  let (ws, error) = await verifyWebsocketRequest(req, "myfancyprotocol")
  
  if ws.isNil:
    echo "WS negotiation failed: ", error
    await req.respond(Http400, "Websocket negotiation failed: " & $error)
    req.client.close()
    return
  
  echo "New websocket customer arrived!"
  while true:
    let (opcode, data) = await ws.readData()
    try:
      echo "(opcode: ", opcode, ", data length: ", data.len, ")"
      
      case opcode
      of Opcode.Text:
        await ws.sendText("thanks for the data!")
      of Opcode.Binary:
        await ws.sendBinary(data)
      of Opcode.Close:
        asyncCheck ws.close()
        let (closeCode, reason) = extractCloseData(data)
        echo "socket went away, close code: ", closeCode, ", reason: ", reason
      else: discard
    except:
      echo "encountered exception: ", getCurrentExceptionMsg()

waitFor server.serve(Port(8080), cb)

Types

HeaderVerificationError {...}{.pure.} = enum
  None,                       ## No error.
  UnsupportedVersion, ## The Sec-Websocket-Version header gave an unsupported version.
                     ## The only currently supported version is 13.
  NoKey,                      ## No Sec-Websocket-Key was provided.
  ProtocolAdvertised,         ## A protocol was advertised but the server gave no protocol.
  NoProtocolsSupported,       ## None of the advertised protocols match the server protocol.
  NoProtocolAdvertised        ## Server asked for a protocol but no protocol was advertised.
  Source Edit

Procs

proc `$`(error: HeaderVerificationError): string {...}{.raises: [], tags: [].}
  Source Edit
proc makeHandshakeResponse(key, protocol: string): string {...}{.raises: [], tags: [].}
  Source Edit
proc verifyWebsocketRequest(client: AsyncSocket; headers: HttpHeaders; protocol = ""): Future[
    tuple[ws: AsyncWebSocket, error: HeaderVerificationError]] {...}{.
    raises: [Exception, ValueError, FutureError], tags: [RootEffect].}
Verifies the request is a websocket request:
  • Supports protocol version 13 only
  • Does not support extensions (yet)
  • Will auto-negotiate a compatible protocol based on your protocol param

If all validations pass, will give you a tuple (AsyncWebSocket, ""). You can pass in a empty protocol param to not perform negotiation; this is the equivalent of accepting all protocols the client might request.

If the client does not send any protocols, but you have given one, the request will fail.

If validation FAILS, the response will be (nil, human-readable failure reason).

After successful negotiation, you can immediately start sending/reading websocket frames.

  Source Edit
proc verifyWebsocketRequest(req: asynchttpserver.Request; protocol = ""): Future[
    tuple[ws: AsyncWebSocket, error: HeaderVerificationError]] {...}{.
    raises: [Exception, ValueError, FutureError], tags: [RootEffect].}
Convenience wrapper for AsyncHttpServer requests.   Source Edit