Written from a line-by-line source review; every example output is from a real run.
Introduction
The callbackhttp 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 asyncmeta
The plugin is fully built on the asyncmeta constants. `Capabilities()` returns exactly the `asyncmeta.ProfileRouteControl()` bitmask (=2442): WaitDrained | RouteMeta | RouteInfo | RouteClose | Known. `RouteState` returns `asyncmeta.RouteStateOpen` (=1) / `RouteStateClosed` (=0), and `RouteMeta(listenerId, key)` knows the `asyncmeta.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: callbackhttp 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.
Loading the plugin
plugin "../plugins/print/PrintPlugin"; plugin "../plugins/async_meta/AsyncMetaPlugin"; plugin "../plugins/callback_http_listener/CallbackHttpListenerPlugin";
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 = callbackhttp.Open("OnRequest", -1, 8080,
callbackhttp.BindLocalOnly());
// ... the server runs on the accept thread ...
callbackhttp.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 asyncmeta 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.
`BindMode` codes: 0 = BindLocalOnly (default), 1 = BindAny. `BindModeText` in text: “local” or “any”.
State / RouteState return asyncmeta.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; `RouteCloseAccepted` becomes 1 afterward. `Close` shuts 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`/`listen` failure, 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 `callbackhttp.BindLocalOnly()` or `callbackhttp.BindAny()`. listenerId is the positive id given by Open. metaKey is one of the asyncmeta.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.
callbackhttp.Capabilities
callbackhttp.Capabilities() -> int
Returns the listener's capability bitmask matching the asyncmeta constants.
This function takes no arguments.
asyncmeta.ProfileRouteControl (=2442): WaitDrained | RouteMeta | RouteInfo | RouteClose | Known.
printf("%d\n", callbackhttp.Capabilities());
printf("%d\n", (callbackhttp.Capabilities() ==
asyncmeta.ProfileRouteControl()));2442 1
For backend capability checking with the Supports* helpers. Worker plugins (e.g. callbackworker = 3701) and listener plugins (callbackhttp = 2442) return different bitmasks — so code can adapt automatically.
callbackhttp.BindLocalOnly
callbackhttp.BindLocalOnly() -> int
Returns the constant value of the “loopback only” bind mode.
This function takes no arguments.
0.
printf("%d\n", callbackhttp.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.
callbackhttp.BindAny
callbackhttp.BindAny() -> int
Returns the constant value of the “any interface” bind mode.
This function takes no arguments.
1.
printf("%d\n", callbackhttp.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.
callbackhttp.Open
callbackhttp.Open(callbackName, timeoutMs, port?, bindMode?) -> int
Opens 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: callbackhttp.BindLocalOnly() (0, default) or callbackhttp.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 = callbackhttp.Open("OnRequest", -1, 0,
callbackhttp.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.
callbackhttp.Close
callbackhttp.Close(listenerId) -> int
Closes 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.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.
callbackhttp.Port
callbackhttp.Port(listenerId) -> int
Returns the listener's actual, bound TCP port.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The port (1..65535).
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", (callbackhttp.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.
callbackhttp.BindMode
callbackhttp.BindMode(listenerId) -> int
Returns the listener's bind-mode constant.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
callbackhttp.BindLocalOnly() (=0) or callbackhttp.BindAny() (=1).
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0,
callbackhttp.BindLocalOnly());
printf("%d\n", callbackhttp.BindMode($lid));0
For programmatic bind-mode checking: compare against BindLocalOnly() / BindAny(). Useful for logging or security audits.
callbackhttp.BindModeText
callbackhttp.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 = callbackhttp.Open("OnRequest", -1, 0,
callbackhttp.BindLocalOnly());
printf("%s\n", callbackhttp.BindModeText($lid));local
For logging, developer UI. Textual counterpart of BindMode.
callbackhttp.State
callbackhttp.State(listenerId) -> int
Returns the listener's state using the asyncmeta route-state constants.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
asyncmeta.RouteStateOpen (=1) if open; asyncmeta.RouteStateClosed (=0) if closed.
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.State($lid));1
For programmatic state checking. Shared vocabulary with the callback_* family: comparing with asyncmeta.RouteStateOpen makes the code uniform and portable.
callbackhttp.StateText
callbackhttp.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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%s\n", callbackhttp.StateText($lid));open
For logging or UI display. Textual counterpart of State's numeric value.
callbackhttp.OpenCount
callbackhttp.OpenCount() -> int
Returns 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", callbackhttp.OpenCount());
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.OpenCount());
callbackhttp.Close($lid);
printf("%d\n", callbackhttp.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.
callbackhttp.Active
callbackhttp.Active(listenerId) -> int
Returns the number of requests currently being processed.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of active requests (>= 0).
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.Active($lid));0
For monitoring the server's current load. 0 with no traffic; a high value may signal congestion.
callbackhttp.Pending
callbackhttp.Pending(listenerId) -> int
Returns the number of pending (not yet started) requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of pending requests.
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.Pending($lid));0
An early signal of input congestion. A high Pending shows that callbacks are slow and requests pile up.
callbackhttp.Queued
callbackhttp.Queued(listenerId) -> int
Returns the number of queued requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of queued requests.
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.Queued($lid));0
For monitoring the internal queue length. Pending + Queued together give the full waiting picture.
callbackhttp.Running
callbackhttp.Running(listenerId) -> int
Returns the number of currently running requests (in-callback).
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of running requests.
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.Running($lid));0
For monitoring parallelism: if too high, look at callback performance or lower timeoutMs.
callbackhttp.Drained
callbackhttp.Drained(listenerId) -> int
Tells 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.Drained($lid));1
Before clean shutdown: ensure Drained is 1 before calling Close. With traffic, WaitDrained blocks for this.
callbackhttp.WaitDrained
callbackhttp.WaitDrained(listenerId, timeoutMs) -> int
Blocks 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.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.
callbackhttp.Info
callbackhttp.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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%s\n", callbackhttp.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 asyncmeta vocabulary. One listener has one route; the Route* verbs use the async meta model's terminology.
callbackhttp.RouteState
callbackhttp.RouteState(listenerId) -> int
Returns the route's state using the asyncmeta route-state constants.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
asyncmeta.RouteStateOpen (=1) or RouteStateClosed (=0).
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RouteState($lid));1
Value equivalent to State (one listener, one route), but using the asyncmeta terminology in the Route* family. Use it when you want code uniform with other route-controlled backends.
callbackhttp.RouteStateText
callbackhttp.RouteStateText(listenerId) -> string
Returns the route's state in text.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
“open” or “closed”.
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%s\n", callbackhttp.RouteStateText($lid));open
For logging or UI display in the Route* family.
callbackhttp.RouteCallback
callbackhttp.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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%s\n", callbackhttp.RouteCallback($lid));OnRequest
For diagnostics or reflectivity: confirming the callback name bound to the listener, e.g. in log messages.
callbackhttp.RouteTimeout
callbackhttp.RouteTimeout(listenerId) -> int
Returns 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RouteTimeout($lid));-1
Reflective query of configuration. -1 means infinite wait — no forced shutdown time limit for the callback.
callbackhttp.RouteKnown
callbackhttp.RouteKnown(listenerId) -> int
Tells 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RouteKnown($lid));1
Defensive check before a Route* query. A 0 signals the listener is no longer active.
callbackhttp.RouteMeta
callbackhttp.RouteMeta(listenerId, metaKey) -> int
Returns a specific meta field of the route by asyncmeta.RouteMeta* keys.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
| metaKey | int | An asyncmeta.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 asyncmeta documentation).
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RouteMeta($lid,
asyncmeta.RouteMetaState()));
printf("%d\n", callbackhttp.RouteMeta($lid,
asyncmeta.RouteMetaDrained()));1 1
One uniform query on the route's state — with the exact keys from the asyncmeta vocabulary. If your code is portable across several backends, this form is the portable query.
callbackhttp.RouteInfo
callbackhttp.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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", (str.Len(callbackhttp.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 asyncmeta terminology), and the route shutdown process.
callbackhttp.RoutePending
callbackhttp.RoutePending(listenerId) -> int
Returns the number of route-level pending requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of pending requests.
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RoutePending($lid));0
Equivalent to listener-level Pending (with one route). The Route* family follows the asyncmeta terminology.
callbackhttp.RouteQueued
callbackhttp.RouteQueued(listenerId) -> int
Returns the number of route-level queued requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of queued requests.
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RouteQueued($lid));0
Equivalent to listener-level Queued. For monitoring congestion.
callbackhttp.RouteRunning
callbackhttp.RouteRunning(listenerId) -> int
Returns the number of route-level currently running requests.
| Parameter | Type | Description |
|---|---|---|
| listenerId | int | The listener id. |
The number of running requests.
i64 $lid;
$lid = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RouteRunning($lid));0
Equivalent to listener-level Running. For monitoring parallelism.
callbackhttp.RouteDrained
callbackhttp.RouteDrained(listenerId) -> int
Tells 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RouteDrained($lid));1
Equivalent to listener-level Drained. For pre-shutdown clean-state verification.
callbackhttp.WaitRouteDrained
callbackhttp.WaitRouteDrained(listenerId, timeoutMs) -> int
Blocks 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.WaitRouteDrained($lid, 50));1
Route-level counterpart of WaitDrained. In the two-phase shutdown pattern, call AFTER RouteClose, before fully stopping with Close.
callbackhttp.RouteCloseAccepted
callbackhttp.RouteCloseAccepted(listenerId) -> int
Tells 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 = callbackhttp.Open("OnRequest", -1, 0);
callbackhttp.RouteClose($lid);
printf("%d\n", callbackhttp.RouteCloseAccepted($lid));1
For confirming the two-phase shutdown: RouteClose returned 1, and this also returns 1 — shutdown is in progress.
callbackhttp.RouteClosedQueued
callbackhttp.RouteClosedQueued(listenerId) -> int
Tells 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.RouteClosedQueued($lid));0
For finer-grained shutdown phase tracking: after RouteClose acceptance, this becomes 1 when the background thread actually starts the shutdown.
callbackhttp.RouteCloseInfo
callbackhttp.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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", (str.Len(callbackhttp.RouteCloseInfo($lid)) >
0));1
Extended version of RouteInfo: also contains shutdown process fields (closeAccepted, closedQueued). For detailed shutdown logging.
callbackhttp.RouteClose
callbackhttp.RouteClose(listenerId) -> int
Requests 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 = callbackhttp.Open("OnRequest", -1, 0);
printf("%d\n", callbackhttp.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 callbackhttp 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 callback_listener / callback_tcp_listener: those plugins may have MULTIPLE routes (one listener with several path handlers), and there the two levels give different values. In callbackhttp, 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.
The callbacklistener generic async listener plugin
Three-layer subscription / route / job model, full asyncmeta vocabulary, two-step shutdown — complete function reference