Lesson 12 of 16

Networking & Web

HTTP client, TCP sockets, web server

download this lesson (.md) ↓ all lessons

12. Networking & Web

HTTP client

Fetch from the web and combine with json_parse to call APIs:

let page = http_get("https://example.com");
print(len(page), "characters");

let body = http_post("https://httpbin.org/post", "hello=world");
print(body);

Both return the response body as a string, or null on failure.

Web server — build a backend

serve(port, handler) starts an HTTP server. For every request it calls your handler function with a request dict and uses the returned value as the response.

func route(req) {
    let path = req["path"];        // also: req["method"], req["body"]
    if (path == "/") {
        return "<h1>Hello from STencil!</h1>";
    }
    elif (path == "/json") {
        return {
            "type": "application/json",
            "body": json_str({ "ok": true, "lang": "STencil" })
        };
    }
    else {
        return { "status": 404, "body": "Not found: " + path };
    }
}

serve(8080, route);   // blocks, serving forever

Run it, then open http://localhost:8080 in a browser.

The request dict

Key Value
method "GET", "POST", ...
path the URL path, e.g. "/json"
body request body as a string

The response

  • Return a string → sent as the body with status 200, text/html.
  • Return a dict with optional status (int), body (string), type (content-type).

Reading the port from the environment (for hosting)

Hosts like Railway provide the port in $PORT:

let port = env("PORT");
serve(int(port), route);

Raw TCP sockets

Lower-level networking when HTTP isn't enough:

let sock = tcp_connect("example.com", 80);   // returns an id, or -1 on failure
if (sock > 0) {
    tcp_send(sock, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n");
    let response = tcp_recv(sock);            // read available bytes (5s timeout)
    print(split(response, "\r\n")[0]);        // HTTP/1.1 200 OK
    tcp_close(sock);
}

Next: Graphics & Games