Introduction
The http_server plugin provides a simple, callback-based HTTP
server: Open binds a TCP port and forwards every incoming HTTP request
to a script-level callback. The callback receives the RAW HTTP request
bytes (the request line, headers, and body) and returns a raw HTTP
response blob — the plugin sends it straight back to the client. Request
parsing and response building are the script's job (or a helper
plugin's), so the solution is minimal but fully flexible.
Relationship to async_meta
The plugin is fully built on the async_meta constants.
Capabilities() returns exactly the async_meta.ProfileRouteControl()
bitmask (=2442): WaitDrained | RouteMeta | RouteInfo | RouteClose |
Known. RouteState returns async_meta.RouteStateOpen (=1) /
RouteStateClosed (=0), and RouteMeta(listenerId, key) knows the
async_meta.RouteMeta* keys (State, Timeout, Pending, Queued, Running,
Drained, Known, CloseAccepted, ClosedQueued).
One listener = one route
It is important to understand the plugin's design choice:
http_server is NOT a URL router. Every Open call creates a single
listener with a single route (= a single callback). Incoming HTTP
request URLs are NOT resolved by the plugin — the entire raw request
reaches the callback, and the callback decides what to do (path-based
routing, static file, REST handler, etc.). For multiple route handlers,
open several listeners on different ports, or branch in a single
callback on the request line.
Two bind modes
The fourth (optional) argument of Open is the bind mode.
BindLocalOnly (=0): listens only on the loopback (127.0.0.1)
interface, safe for sandbox development and testing. BindAny (=1):
listens on every interface (0.0.0.0), reachable from other hosts on the
network — use it only when you intentionally publish a service. The
default is BindLocalOnly if the argument is not provided.
Peer metadata: the extended callback forms
The handler may declare extra parameters, and the host fills them in with the client's identity — useful for access logs, IP-based filtering, or mTLS-based authorization:
callback i32 NAME(ref blob $Request)— payload only.callback i32 NAME(ref blob $Request, string $PeerHost, i32 $PeerPort)— plus the client's address and port.callback i32 NAME(ref blob $Request, string $PeerHost, i32 $PeerPort, string $PeerCertSubject)— plus the client certificate's subject when the connection is mTLS-verified (empty when there is no TLS, or when an optional-mode client presented no certificate).
The same forms work on the TCP and UDP callback families, so a handler moves between transports unchanged.
Loading the plugin
plugin "builtin:print"; plugin "../plugins/async_meta/AsyncMetaPlugin"; plugin "../plugins/http_server/HttpServerPlugin";
A typical flow — minimal HTTP server
callback i32 OnRequest(ref blob $Request) { // The callback receives the RAW HTTP request as a blob. // Modify the blob with the response, or return a new blob. return(1); } i32 main() { i64 $lid; $lid = http_server.Open("OnRequest", -1, 8080, http_server.BindLocalOnly()); // ... the server runs on the accept thread ... http_server.Close($lid); return(0); }
Two-step shutdown: RouteClose, then Close
The plugin offers two shutdown phases. (1) RouteClose(listenerId)
signals the route is to be closed: no new requests, but already running
callbacks finish. WaitRouteDrained(listenerId, timeoutMs) can then be
awaited. (2) Close(listenerId) is the full listener (TCP socket +
accept thread) shutdown. In simpler cases just Close is enough — it
implicitly performs the former too.
Listener- and route-level queries
Many query functions in the plugin distinguish two levels. The LISTENER level (Port, BindMode/Text, State/Text, Active, Pending, Queued, Running, Drained, WaitDrained, Info, OpenCount) describes the TCP socket and active/queued requests. The ROUTE level (RouteState/Text, RouteCallback, RouteTimeout, RouteKnown, RouteMeta, RouteInfo, RoutePending, RouteQueued, RouteRunning, RouteDrained, WaitRouteDrained, RouteCloseAccepted, RouteClosedQueued, RouteCloseInfo, RouteClose) works in the async meta model and uses async_meta constants for its key codes. With one listener, both levels show identical states; the distinction matters for the shared vocabulary with multi-route listeners (TCP/general).
What to know about every function (the basics)
The callback receives RAW HTTP request bytes as a blob; the response is a RAW HTTP response blob the plugin writes back to the socket directly.
BindModecodes: 0 = BindLocalOnly (default), 1 = BindAny.BindModeTextin text: “local” or “any”.State / RouteState return async_meta.RouteStateOpen (=1) / RouteStateClosed (=0); the *Text counterparts in text.
WaitDrained and WaitRouteDrained return 1 if drained occurs before the timeoutMs expires; 0 if it expired.
RouteClose closes the route layer;
RouteCloseAcceptedbecomes 1 afterward.Closeshuts down the whole listener (TCP socket + thread).Two-step shutdown rule: if you first call RouteClose successfully (1), then Close, Close returns 0 (because the listener is no longer in active state when Close is called — the route layer was already closed).
port = 0 makes the OS pick the port; the actual port is queried with
Port($lid).An error (stopping the script) is caused by a wrong argument count or type, an out-of-range port (0..65535) or timeoutMs, an invalid bind mode, an already-closed listener, a
bind/listenfailure, and a thread startup failure.
How to read the signatures
callbackName is the script-level request callback name (callback i32 NAME(ref blob $X)). timeoutMs is the callback's run-time limit in ms;
-1 = infinite. port is the TCP port (0..65535; 0 = OS picks). bindMode
is the integer returned by http_server.BindLocalOnly() or
http_server.BindAny(). listenerId is the positive id given by Open.
metaKey is one of the async_meta.RouteMeta* values. The type after the
-> arrow is the return type.
Lifecycle and bind configuration
Plugin capability query, bind-mode constants, and listener open/close.
http_server.Capabilities
http_server.Capabilities() -> intReturns the listener's capability bitmask matching the async_meta constants.
This function takes no arguments.
async_meta.ProfileRouteControl (=2442): WaitDrained | RouteMeta | RouteInfo | RouteClose | Known.
printf("%d\n", http_server.Capabilities()); printf("%d\n", (http_server.Capabilities() == async_meta.ProfileRouteControl()));
2442 1
For backend capability checking with the Supports* helpers. Worker plugins (e.g. worker = 3701) and listener plugins (http_server = 2442) return different bitmasks — so code can adapt automatically.
http_server.BindLocalOnly
http_server.BindLocalOnly() -> intReturns the constant value of the “loopback only” bind mode.
This function takes no arguments.
0.
printf("%d\n", http_server.BindLocalOnly());
0
For the fourth argument of Open, when you want a safe local server (sandbox development, test environment). This is the default mode if the bindMode argument is not given.
http_server.BindAny
http_server.BindAny() -> intReturns the constant value of the “any interface” bind mode.
This function takes no arguments.
1.
printf("%d\n", http_server.BindAny());
1
When the HTTP server should be reachable from other hosts (public service). Use it only as a conscious choice for security reasons — the loopback-only mode is safer by default.
http_server.OpenTls
http_server.OpenTls(certFile, keyFile, callbackName, timeoutMs, port?, bindMode?) -> listener idOpens an HTTPS listener in a SINGLE call. The listener is TLS from birth — unlike an Open + EnableTls pair, no plaintext window ever exists. The certificate, the key and the TLS provider are pre-flight-checked at open time, so a bad path fails here with a clean, script-visible error instead of silently dropping connections later.
| Parameter | Type | Description |
|---|---|---|
| certFile | string | Path to the server certificate chain (PEM). |
| keyFile | string | Path to the matching private key (PEM). |
| callbackName | string | The script-level callback to dispatch requests to. |
| timeoutMs | int | The callback's run-time limit in milliseconds. |
| port | int | Optional. 0 (or omitted) lets the OS pick; read it back with Port. |
| bindMode | int | Optional. BindLocalOnly (0, default) or BindAny (1). |
Returns a positive listener id, or a negative value on failure.
The TLS layer lives in the tls plugin, which this plugin loads on demand — the script needs no tls import of its own.
http_server.EnableTls
http_server.EnableTls(listenerId, certFile, keyFile) -> 0
Upgrades an already-open listener: connections accepted from then on are TLS-wrapped. The exact counterpart of tcp_server.EnableTls. Prefer OpenTls when you can — it leaves no plaintext window between Open and the upgrade.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id returned by Open. |
| certFile | string | Path to the server certificate chain (PEM). |
| keyFile | string | Path to the matching private key (PEM). |
Returns 0 on success.
http_server.SetClientCa
http_server.SetClientCa(listenerId, caFile, mode) -> 0
Turns on mTLS: requires (mode 2) or accepts (mode 1) a client certificate signed by the given CA. Call it BEFORE EnableTls / OpenTls-accepted connections — the TLS objects inherit the mode. With mTLS on, the 4-parameter callback form receives the verified client's certificate subject.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
| caFile | string | Path to the CA bundle (PEM) that client certificates are verified against. |
| mode | int | 1 = optional (accept a certificate if offered), 2 = required (reject clients without a valid one). |
Returns 0 on success.
http_server.Open
http_server.Open(callbackName, timeoutMs, port?, bindMode?) ->
intOpens an HTTP listener on a TCP port and forwards incoming requests to the callback via an accept thread.
| Parameter | Type | Description |
|---|---|---|
| callbackName | string | The script-level callback name to call. Signature: callback i32 NAME(ref blob $X). |
| timeoutMs | int | The callback's run-time limit in ms. -1 = infinite; otherwise 0..2147483647. |
| port | int | Optional TCP port (0..65535). 0 lets the OS pick. Default: 0. |
| bindMode | int | Optional bind mode: http_server.BindLocalOnly() (0, default) or http_server.BindAny() (1). |
The listenerId (positive i64). A bad argument, a bind failure, or a thread startup failure raises a runtime error.
callback i32 OnRequest(ref blob $X) { return(1); } i64 $lid; $lid = http_server.Open("OnRequest", -1, 0, http_server.BindLocalOnly()); printf("%d\n", ($lid > 0));
1
For starting a local HTTP service (debug server, local REST API, static file server). The 0-port is handy in CI/test environments. The returned listenerId is the input of every further operation.
http_server.Close
http_server.Close(listenerId) -> intCloses the listener: stops the accept thread, shuts down the socket, and releases resources.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The positive listenerId from Open. |
1 if the listener was open and closed successfully; 0 if it was already closed (e.g. after a prior RouteClose). An unknown or non-positive listenerId raises a runtime error.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.Close($lid));
1
For clean listener shutdown at the script's end. Close waits for in-progress callbacks to finish, so it gives a clean-state shutdown. If you called RouteClose first, Close returns 0 (the listener was no longer active).
Listener-level state
Current state of the active listener: bound port and mode, “open/closed” state, and a plugin-level OpenCount.
http_server.Port
http_server.Port(listenerId) -> intReturns the listener's actual, bound TCP port.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The port (1..65535).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", (http_server.Port($lid) > 0));
1
Particularly useful when you passed port=0 to Open (asking for an OS-picked port). You query the returned port number with this to advertise to clients.
http_server.BindMode
http_server.BindMode(listenerId) -> intReturns the listener's bind-mode constant.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
http_server.BindLocalOnly() (=0) or http_server.BindAny() (=1).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0, http_server.BindLocalOnly()); printf("%d\n", http_server.BindMode($lid));
0
For programmatic bind-mode checking: compare against BindLocalOnly() / BindAny(). Useful for logging or security audits.
http_server.BindModeText
http_server.BindModeText(listenerId) -> string
Returns the bind mode in human-readable text.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
“local” for BindLocalOnly; “any” for BindAny.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0, http_server.BindLocalOnly()); print.Line(http_server.BindModeText($lid));
local
For logging, developer UI. Textual counterpart of BindMode.
http_server.State
http_server.State(listenerId) -> intReturns the listener's state using the async_meta route-state constants.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
async_meta.RouteStateOpen (=1) if open; async_meta.RouteStateClosed (=0) if closed.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.State($lid));
1
For programmatic state checking. Shared vocabulary with the callback_* family: comparing with async_meta.RouteStateOpen makes the code uniform and portable.
http_server.StateText
http_server.StateText(listenerId) -> string
Returns the listener's state as text.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
“open” if open; “closed” if closed.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); print.Line(http_server.StateText($lid));
open
For logging or UI display. Textual counterpart of State's numeric value.
http_server.OpenCount
http_server.OpenCount() -> intReturns the number of currently open HTTP listeners (plugin-level, global view).
This function takes no arguments.
The number of open listeners (0 if none).
printf("%d\n", http_server.OpenCount()); i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.OpenCount()); http_server.Close($lid); printf("%d\n", http_server.OpenCount());
0 1 0
For resource control and diagnostics: if it does not return to 0 after Close, it signals a resource leak.
Listener-level traffic
Current traffic metrics of the listener: active, pending, queued, running requests; drain state and blocking wait.
http_server.Active
http_server.Active(listenerId) -> intReturns the number of requests currently being processed.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of active requests (>= 0).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.Active($lid));
0
For monitoring the server's current load. 0 with no traffic; a high value may signal congestion.
http_server.Pending
http_server.Pending(listenerId) -> intReturns the number of pending (not yet started) requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of pending requests.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.Pending($lid));
0
An early signal of input congestion. A high Pending shows that callbacks are slow and requests pile up.
http_server.Queued
http_server.Queued(listenerId) -> intReturns the number of queued requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of queued requests.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.Queued($lid));
0
For monitoring the internal queue length. Pending + Queued together give the full waiting picture.
http_server.Running
http_server.Running(listenerId) -> intReturns the number of currently running requests (in-callback).
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of running requests.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.Running($lid));
0
For monitoring parallelism: if too high, look at callback performance or lower timeoutMs.
http_server.Drained
http_server.Drained(listenerId) -> intTells whether the listener is “drained” (no active, pending, queued, or running request).
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
1 if drained; 0 if something is in progress.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.Drained($lid));
1
Before clean shutdown: ensure Drained is 1 before calling Close. With traffic, WaitDrained blocks for this.
http_server.WaitDrained
http_server.WaitDrained(listenerId, timeoutMs) -> intBlocks until the listener is fully drained, or the timeoutMs expires.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
| timeoutMs | int | Maximum wait in ms; -1 = infinite. |
1 if drain occurred before timeoutMs expired; 0 if it expired.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.WaitDrained($lid, 50));
1
For a simple, correct shutdown pattern: call this after RouteClose so every in-progress callback can finish. On expired timeout, you can decide on a forced shutdown via Close.
http_server.Info
http_server.Info(listenerId) -> string
Returns the listener's aggregated key=value diagnostic state as a string.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
A space-separated key=value list (id, state, callback, timeout, port, bind, bindCode, active).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); print.Line(http_server.Info($lid));
id=1 state=open callback=OnRequest timeout=-1 port=<auto> bind=local bindCode=0 active=0
For detailed diagnostics in a single call. The keys are stable; easy to parse with str.* operations.
Route-level state
The state of the listener's route layer, in the async_meta vocabulary. One listener has one route; the Route* verbs use the async meta model's terminology.
http_server.RouteState
http_server.RouteState(listenerId) -> intReturns the route's state using the async_meta route-state constants.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
async_meta.RouteStateOpen (=1) or RouteStateClosed (=0).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteState($lid));
1
Value equivalent to State (one listener, one route), but using the async_meta terminology in the Route* family. Use it when you want code uniform with other route-controlled backends.
http_server.RouteStateText
http_server.RouteStateText(listenerId) -> string
Returns the route's state in text.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
“open” or “closed”.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); print.Line(http_server.RouteStateText($lid));
open
For logging or UI display in the Route* family.
http_server.RouteCallback
http_server.RouteCallback(listenerId) -> string
Returns the callback name passed at Open.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The callback name as text.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); print.Line(http_server.RouteCallback($lid));
OnRequest
For diagnostics or reflectivity: confirming the callback name bound to the listener, e.g. in log messages.
http_server.RouteTimeout
http_server.RouteTimeout(listenerId) -> intReturns the callback's run-time max value in milliseconds.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The timeoutMs (the value passed at Open); -1 for infinite wait.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteTimeout($lid));
-1
Reflective query of configuration. -1 means infinite wait — no forced shutdown time limit for the callback.
http_server.RouteKnown
http_server.RouteKnown(listenerId) -> intTells whether the route bound to the listener is known (= the listener is open).
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
1 if known; 0 if the listener is already closed or unknown.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteKnown($lid));
1
Defensive check before a Route* query. A 0 signals the listener is no longer active.
http_server.RouteMeta
http_server.RouteMeta(listenerId, metaKey) -> intReturns a specific meta field of the route by async_meta.RouteMeta* keys.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
| metaKey | int | An async_meta.RouteMeta* value (State=1, Timeout=2, Pending=3, Queued=4, Running=5, Drained=6, Known=7, CloseAccepted=8, ClosedQueued=9). |
The value matching the field (see the async_meta documentation).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteMeta($lid, async_meta.RouteMetaState())); printf("%d\n", http_server.RouteMeta($lid, async_meta.RouteMetaDrained()));
1 1
One uniform query on the route's state — with the exact keys from the async_meta vocabulary. If your code is portable across several backends, this form is the portable query.
http_server.RouteInfo
http_server.RouteInfo(listenerId) -> string
Returns the route's aggregated key=value diagnostic state as a string.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
A space-separated key=value list (id, state, stateCode, callback, timeout, port, bind, bindCode, drained, pending, queued, running, active).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", (str.Len(http_server.RouteInfo($lid)) > 0));
1
For a complete route state snapshot in one call. Broader than Info — also includes the traffic metrics.
Route-level traffic and shutdown
Traffic measured at the route layer (equivalent to the listener level, only with the async_meta terminology), and the route shutdown process.
http_server.RoutePending
http_server.RoutePending(listenerId) -> intReturns the number of route-level pending requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of pending requests.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RoutePending($lid));
0
Equivalent to listener-level Pending (with one route). The Route* family follows the async_meta terminology.
http_server.RouteQueued
http_server.RouteQueued(listenerId) -> intReturns the number of route-level queued requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of queued requests.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteQueued($lid));
0
Equivalent to listener-level Queued. For monitoring congestion.
http_server.RouteRunning
http_server.RouteRunning(listenerId) -> intReturns the number of route-level currently running requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of running requests.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteRunning($lid));
0
Equivalent to listener-level Running. For monitoring parallelism.
http_server.RouteDrained
http_server.RouteDrained(listenerId) -> intTells whether the route is “drained” (pending = queued = running = 0).
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
1 if drained; 0 if something is in progress.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteDrained($lid));
1
Equivalent to listener-level Drained. For pre-shutdown clean-state verification.
http_server.WaitRouteDrained
http_server.WaitRouteDrained(listenerId, timeoutMs) -> intBlocks until the route is fully drained, or the timeoutMs expires.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
| timeoutMs | int | Maximum wait in ms; -1 = infinite. |
1 if drain occurred before timeoutMs expired; 0 if it expired.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.WaitRouteDrained($lid, 50));
1
Route-level counterpart of WaitDrained. In the two-phase shutdown pattern, call AFTER RouteClose, before fully stopping with Close.
http_server.RouteCloseAccepted
http_server.RouteCloseAccepted(listenerId) -> intTells whether the RouteClose request has been accepted.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
1 if yes; 0 if no (no RouteClose yet, or rejected).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); http_server.RouteClose($lid); printf("%d\n", http_server.RouteCloseAccepted($lid));
1
For confirming the two-phase shutdown: RouteClose returned 1, and this also returns 1 — shutdown is in progress.
http_server.RouteClosedQueued
http_server.RouteClosedQueued(listenerId) -> intTells whether the route shutdown has been queued (the background thread is processing it).
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
1 if yes; 0 if not yet.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteClosedQueued($lid));
0
For finer-grained shutdown phase tracking: after RouteClose acceptance, this becomes 1 when the background thread actually starts the shutdown.
http_server.RouteCloseInfo
http_server.RouteCloseInfo(listenerId) -> string
Returns the detailed key=value diagnostic state of the route shutdown process.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
A space-separated key=value list (id, state, callback, timeout, port, bind, drained, pending, queued, running, active, closeAccepted, closedQueued).
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", (str.Len(http_server.RouteCloseInfo($lid)) > 0));
1
Extended version of RouteInfo: also contains shutdown process fields (closeAccepted, closedQueued). For detailed shutdown logging.
http_server.RouteClose
http_server.RouteClose(listenerId) -> intRequests the route shutdown: no new requests, in-progress ones finish.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
1 if the plugin accepted the request; 0 if the route is already closed.
i64 $lid; $lid = http_server.Open("OnRequest", -1, 0); printf("%d\n", http_server.RouteClose($lid));
1
First step of the two-phase shutdown. Call this first, then WaitRouteDrained for in-progress requests to finish, finally Close for the full listener shutdown.
Practical notes
What the http_server plugin is good for
Starting a local HTTP service for sandbox development, test environment, REST API mock.
Static file server: the callback returns file contents in an HTTP response blob based on the request URL.
Event-driven processing: every HTTP request is a callback invocation; the script can focus on the content.
Full control at the HTTP protocol level: the plugin does not interpret or restrict — the callback decides whether to parse or delegate.
Processing the callback blob
The callback receives the RAW HTTP request bytes — across the request
line, headers, and (any) body. The callback's job is parsing the request
(at least extracting the method, URL, and headers) and producing a RAW
HTTP response blob. The response blob must be in proper HTTP format:
HTTP/1.1 200 OK\r\nContent-Type: ...\r\nContent-Length: N\r\n\r\n<body>. The plugin sends the blob unchanged — there is
no automatic header or status-code injection.
One listener with one route: the design choice
The plugin offers a single route layer per listener — it is not a URL router. This design choice follows the single-responsibility principle: the plugin only does TCP-level accept and callback forwarding; content-based routing is the callback's or a helper-router's job. For multiple route handlers, either open several listeners on different ports, or branch in a single callback based on the request line (method + URL).
Two-step shutdown pattern
(1) RouteClose: signals new requests are not accepted; in-progress ones may finish. (2) WaitRouteDrained(timeoutMs): blocks until every in-flight callback finishes, or the timeout expires. (3) Close: the full listener (TCP socket + accept thread) shutdown. In simpler cases, Close alone is enough — it implicitly performs the above, but doesn't give fine timing. For high-throughput servers, the two-step method is more flexible.
Listener- and route-level equivalence
A listener has a single route, so Pending == RoutePending, Queued == RouteQueued, etc. The two levels still exist for the shared vocabulary with bus / tcp_server: those plugins may have MULTIPLE routes (one listener with several path handlers), and there the two levels give different values. In http_server, both show the same — pick the one that fits your code style.
Error handling
A wrong argument count or type, an out-of-range port (0..65535) or
timeoutMs, an invalid bind mode, a failed bind/listen, a thread
startup failure, and touching an already-closed listener are reported by
the runtime as a runtime error, and the script stops. Close signals an
open listener with 1 and an already-closed (or RouteClose-handled) one
with 0 — but both are successful call results.