Web libraries

These are pure-Langoost libraries shipped in the lib/ directory, written on top of the net.* primitives. You import them by name. They are distinct from the built-in http.serve (see HTTP server) — these give you Langoost-level types and handler functions you can read and extend.

Three libraries are covered here: http_server, websocket, and sse.

http_server

An HTTP/1.1 server. Each accepted connection is handled in its own thread.

Types

type Request = {
    method:  string,
    path:    string,
    query:   string,
    version: string,
    headers: string[],    // raw "Key: Value" lines
    body:    string,
}

type Response = {
    status:  int,
    headers: string[],    // raw "Key: Value" lines
    body:    string,
}

Functions

FunctionSignatureDescription
servehttp_server.serve(port: int, handler)bind the port and dispatch handler(req: Request) per connection; blocks forever
headerhttp_server.header(req, name: string) → stringvalue of a header (case-insensitive), or "" if missing
statusTexthttp_server.statusText(code: int) → stringIANA reason phrase for a status code

The handler is called as handler(req) and may return either a string (sent as 200 OK with an auto Content-Type) or a Response for full control. Content-Length and Content-Type are added automatically if you omit them.

Example

import http_server
import { Response } from "http_server"

fn handle(req) {
    if req.path == "/" {
        return "Hello, World!"
    }
    if req.path == "/json" {
        return Response{status: 200, headers: [], body: "{\"ok\":true}"}
    }
    return Response{status: 404, headers: [], body: "Not Found"}
}

http_server.serve(8080, handle)

websocket

A minimal RFC 6455 server-side WebSocket implementation. Use websocket.serve for end-to-end connections; it runs the handshake and hands your handler the raw connection.

Types

type WSRequest = { path: string, headers: string[] }

Functions

FunctionSignatureDescription
servewebsocket.serve(port: int, handler)listen and call handler(conn: int, path: string) after the handshake completes
recvwebsocket.recv(conn: int) → stringread one frame’s payload; void on close/EOF (auto-replies to pings)
sendwebsocket.send(conn: int, msg: string) → boolsend a text frame
sendBinarywebsocket.sendBinary(conn: int, data: string) → boolsend a binary frame
closewebsocket.close(conn: int)send a close frame and close the connection
isUpgradewebsocket.isUpgrade(req) → booltrue if the request is a valid WebSocket upgrade
acceptKeywebsocket.acceptKey(req) → stringcompute the Sec-WebSocket-Accept value, or ""
upgradeHeaderswebsocket.upgradeHeaders(accept: string) → string[]response header lines for a 101 handshake
handshakewebsocket.handshake(conn: int, req) → boolperform the full server-side upgrade on conn

Example

import websocket

fn handle(conn, path) {
    println("ws connected: " + path)
    while true {
        let msg = websocket.recv(conn)
        if typeof(msg) == "void" { break }
        websocket.send(conn, "echo: " + msg)
    }
    websocket.close(conn)
}

websocket.serve(8090, handle)

sse

Server-Sent Events: the connection stays open and the server streams text events to the browser’s EventSource.

Types

type SSERequest = { path: string, headers: string[] }

Functions

FunctionSignatureDescription
servesse.serve(port: int, handler)accept connections and call handler(req, emit); returning from the handler closes the socket
writeHeaderssse.writeHeaders(conn: int) → boolwrite the text/event-stream 200 OK header block
framesse.frame(event: string, data: string) → stringbuild one event payload; event="" uses the default message
frameWithIDsse.frameWithID(event: string, data: string, id: string) → stringbuild an event with a Last-Event-ID hint
retryHintsse.retryHint(ms: int) → stringbuild a reconnect-delay hint frame

The handler is called as handler(req, emit) where req is an SSERequest and emit is fn(event: string, data: string) which writes one event to the client.

Example

import sse
import thread

fn handle(req, emit) {
    let i = 0
    while i < 5 {
        emit("tick", "n=" + toString(i))
        thread.core.sleep(1000)
        i = i + 1
    }
}

sse.serve(8091, handle)