ilusm.dev

net

Full networking stack - HTTP client with GET/POST/PUT/PATCH/DELETE and custom headers, JSON-over-HTTP helpers, WebSocket client and server, UDP connect and listen, DNS lookup, ping, TCP dial/listen/accept, raw HTTP request parsing with chunked transfer decoding, HTTP response building, URL path routing with :param segments, retry with exponential backoff, and binary big-endian u16/u32 framing with length-prefix helpers.

Load with: use net

What this module does

net is the single comprehensive networking module. The HTTP client delegates to host-injected __http_* natives. The TCP, UDP, and WebSocket layers wrap their respective __net_* and __sys_tcp_* natives in clean socket objects with .snd, .rcv, .rcvt (timed), and .cls methods.

The low-level HTTP parser (net.read_req, net.response, net.serve) lets you build an HTTP server directly on top of TCP without a separate framework.

Quick example

use net

# HTTP client
body  = net.get("https://api.example.com/v1/users")
resp  = net.post("https://api.example.com/v1/items", json_body, "application/json")
data  = net.jget("https://api.example.com/v1/me")     # GET + JSON decode
result = net.jpost("https://api.example.com/v1/create", {name:"Alice"}, nil)

# WebSocket
ws  = net.ws("wss://ws.example.com/stream")
ws.snd("hello")
msg = ws.rcv()
ws.cls()

# UDP
sock = net.udp_connect("10.0.0.1:9000")
sock.snd("ping")
reply = sock.rcvt(1000)

# TCP server with routing
routes = [
    {mtd: "GET",  pat: "/api/user/:id", fn: \(req, prm) {c:200, bod: "user " + prm.id}},
    {mtd: "POST", pat: "/api/user",     fn: \(req, prm) {c:201, bod: "created"}}
]
lsn = net.tcp_listen("0.0.0.0:8080")
net.serve(lsn, routes, 8192, 1048576, 5000)

# Retry with exponential backoff
net.retry(\() net.get("https://unstable.example.com/"), 3, 100, 2000)

# Binary framing
frame = net.lp16("hello")   # 2-byte length prefix + data
r     = net.ulp16(frame, 0) # {pl: "hello", pos: 7}

Functions

HTTP client

netget(url) / net.get(url)

HTTP GET. Returns the response body string.

netgethdr(url, hdrs) / net.get_hdr(url, hdrs)

HTTP GET with custom headers object.

netpst(url, body, ctyp) / net.post(url, body, ctyp)

HTTP POST. Default content-type is application/json.

netput(url, body, ctyp) / net.put(…)

HTTP PUT.

netpatch(url, body, ctyp) / net.patch(…)

HTTP PATCH.

netdel(url) / net.del(url)

HTTP DELETE.

netpsthdr(url, body, ctyp, hdrs) / net.post_hdr(…)

HTTP POST with custom headers.

netjget(url) / net.jget(url)

GET and JSON-decode the response.

netjpst(url, obj, ctyp) / net.jpost(…)

JSON-encode obj, POST it, and JSON-decode the response.

WebSocket

netwscon(url) / net.ws(url)

Connects to a WebSocket URL. Returns a socket object with .snd, .rcv, .rcvt(tmo), .cls.

netwssrv(addr) / net.wss(addr)

Starts a WebSocket server. Returns a server object with .acc() (accept next connection) and .cls().

netwsproto(url) / net.ws_proto(url)

Returns "ws" or "wss" from the URL scheme, or nil.

UDP and DNS

netudcon(hp) / net.udp_connect(hp)

Creates a connected UDP socket to host:port.

netudlsn(addr) / net.udp_listen(addr)

Binds a UDP listener on addr.

netdns(name) / net.dns(name)

Resolves a hostname to an IP address.

netping(host) / net.ping(host)

Pings a host. Returns the result.

TCP

nettcpdial(hp) / net.tcp_dial(hp)

Dials a TCP connection to host:port. Returns a socket object.

nettcplsn(hp) / net.tcp_listen(hp)

Binds a TCP listener. Returns a listener handle.

nettcpacp(lsn) / net.tcp_accept(lsn)

Accepts the next incoming TCP connection. Returns a socket object.

nettcpcls(lsn) / net.tcp_close(lsn)

Closes a listener.

HTTP server primitives

netrdr(sock, max_hdr, max_body, tmo_ms) / net.read_req(…)

Reads one HTTP/1.1 request from a socket, handling chunked transfer encoding and Content-Length. Returns {m, p, ver, hdr, body}.

netres(code, reason, hdr, body) / net.response(…)

Builds an HTTP/1.1 response string with status line, headers (Content-Length auto-set), and body.

netone(sock, routes, …) / net.one(…)

Handles one request/response cycle on a socket using a route table.

netserve(lsn, routes, …) / net.serve(…)

Accept loop: accepts connections and calls net.one for each.

netroutematch(pat, path) / net.route_match(pat, path)

Matches a path against a pattern with :param segments. Returns {ok, prm}.

netroutefind(method, path, routes) / net.route_find(…)

Finds the first matching route. Returns {prm, row} or nil.

Chunked transfer and binary framing

netchnk(piece) / net.chunk(piece)

Encodes one chunk in HTTP chunked transfer format.

netchnkall(parts) / net.chunk_all(parts)

Encodes a list of strings as a complete chunked transfer body including the terminator.

netchdec(buf, max_total) / net.chunk_decode(buf, max)

Decodes a chunked transfer body from a buffer. Returns {bod, pos}.

net.be_u16(n) / net.be_u32(n)

Encode an integer as big-endian 2- or 4-byte string.

net.be_u16_at(s, i) / net.be_u32_at(s, i)

Read a big-endian u16/u32 from position i in string s. Returns {v, pos}.

netlp16(s) / net.lp16(s)

Length-prefix encodes s with a 2-byte big-endian length. Max 65535 bytes.

netulp16(s, i) / net.ulp16(s, i)

Decodes a length-prefixed payload from position i. Returns {pl, pos}.

net.lp32(s) / net.ulp32(s, i)

Same as lp16/ulp16 but with a 4-byte length prefix.

Utilities

netretry(fn, attempts, base_ms, cap_ms) / net.retry(…)

Retries fn up to attempts times with exponential backoff starting at base_ms and capped at cap_ms. Throws on final failure.

nethp(hp) / net.hp(hp)

Parses a "host:port" string into a two-element list.

nethost(hp) / net.host(hp)

Returns just the host from "host:port".

netport(hp) / net.port(hp)

Returns the port as an integer.

Notes

  • Requires trl, txt, enc, and jsn.
  • HTTP client requires __http_get, __http_post, etc. from the host.
  • TCP/UDP/WebSocket require __sys_tcp_*, __net_udc, __net_udl, __net_ws, __net_wss.