Net API
The Net API provides:
HTTP(S) helpers
net_http_get(url, timeout_ms?)net_http_post(url, content_type, body, timeout_ms?)
WebSocket client using WinHTTP’s WebSocket support
ws_connect(url, timeout_ms?) -> websocket userdataWebSocket methods:
send_text,send_binary,send_json,recv,poll,is_open,close
Supported URL schemes:
HTTP:
http://,https://WebSocket:
ws://,wss://(internally mapped tohttp:///https://for WinHTTP)Works with hostnames and IP addresses, with or without custom ports.
⚠ These are low-level primitives intended for advanced users. Higher-level helpers/wrappers can be built on top, but are not part of this page.
HTTP API
net_http_get
net_http_getok, status_code, body = net_http_get(url, timeout_ms?)Performs a synchronous HTTP/HTTPS GET.
Parameters
url : stringFull URL:
"https://example.com/api/test""http://127.0.0.1:8080/status"
timeout_ms : number (optional)Total timeout (ms) applied to resolve, connect, send, receive.
0ornil= default WinHTTP timeouts.
Returns
ok : booleantrueif the HTTP request succeeded at the transport level (WinHTTP OK).falseif there was a network/protocol error.
status_code : integerHTTP status code (200, 404, 500, ...)
0if the request failed before a response was received.
body : stringResponse body as raw bytes (Lua string).
Example
net_http_post
net_http_postPerforms a synchronous HTTP/HTTPS POST with a request body.
Parameters
url : stringFull URL, same as
net_http_get.
content_type : stringMIME type, e.g.:
"application/json""application/x-www-form-urlencoded""text/plain; charset=utf-8"
body : stringRequest body as a Lua string (raw bytes).
timeout_ms : number (optional)Same semantics as
net_http_get.
Returns
ok : booleanstatus_code : integerbody : string(Same meaning asnet_http_get.)
Example – POST JSON
WebSocket API
The WebSocket API exposes:
A global constructor:
ws_connect(url, timeout_ms?)A userdata type
net_wswith methods:send_text,send_binary,send_jsonrecv,pollis_open,close
Internally, the implementation uses WinHTTP:
ws://→ internally mapped tohttp://wss://→ internally mapped tohttps://A background receive thread continuously reads frames and pushes complete messages into a queue.
Lua sees messages via
ws:recv()(blocking) orws:poll()(non-blocking).
Global: ws_connect
ws_connectOpens a client WebSocket connection.
Parameters
url : stringWebSocket URL, e.g.:
"wss://ws.postman-echo.com/raw""ws://127.0.0.1:9001/echo"
timeout_ms : number (optional)WinHTTP timeouts (resolve, connect, send, receive).
Returns
On success:
ws : userdata(typenet_ws)A WebSocket object with methods described below.
On failure:
nil, "error string"
Example
WebSocket Object (net_ws)
net_ws)Once connected, you have a userdata with metatable "net_ws", exposing these methods:
ws:send_text(message)ws:send_binary(data)ws:send_json(value)ws:recv()ws:poll()ws:is_open()ws:close(code?)
And metamethods:
__gc– automatic cleanup__tostring–"websocket(open)"or"websocket(closed)"
ws:send_text
ws:send_textSends a UTF-8 text message.
Parameters
message : string– Lua string, treated as UTF-8.
Returns
ok : boolean–trueif the send call succeeded;falseotherwise.
Example
ws:send_binary
ws:send_binarySends a binary WebSocket frame.
Parameters
data : string– raw bytes (Lua string).
⚠ Some public echo servers (e.g. Postman’s) close the connection when they receive binary frames. That’s a server behavior, not a bug in the API.
Returns
ok : boolean
Example
ws:send_json
ws:send_jsonSends a JSON text message. Supports:
value= string: sent directly as UTF-8.value= table: encoded via global Lua functionjson_encode.
Parameters
value : string | tablestring– assumed to already be valid JSON.table– will calljson_encode(value)to produce JSON.
Requirements
For
table:A global function
json_encodemust exist:If
json_encodeis missing or throws,ws:send_jsonraises a Lua error.
Returns
ok : boolean
Example – string
Example – table
ws:recv (blocking)
ws:recv (blocking)Blocking receive that waits for a complete WebSocket message to be available in the queue.
Uses the internal message queue (filled by a background thread).
Does not block WinHTTP directly; it loops until:
A message is dequeued, or
The socket is closed and the queue is empty.
Returns
On message:
msg : string– message payload (text or binary).is_text : booleantruefor text framesfalsefor binary frames
On closed and empty:
nil
⚠ This is a blocking loop with a small sleep (
Sleep(1)). Best used in worker scripts or one-shot tests, not every frame in the UI thread.
Example
ws:poll (non-blocking)
ws:poll (non-blocking)Non-blocking receive from the internal message queue.
You get three possible outcomes:
Message available
msg : string– message payloadis_text_or_closed : boolean–true= text,false= binary
No message yet, still open
msg = nilis_text_or_closedis nil
Socket closed and queue empty
msg = nilis_text_or_closed = false
This makes it easy to integrate in per-frame loops:
msg != nil→ handle itmsg == nil and is_text_or_closed == nil→ nothing yetmsg == nil and is_text_or_closed == false→ closed
Example: per-frame polling
ws:is_open
ws:is_openChecks whether the socket is currently open.
Reflects the internal
is_openflag updated by the background thread and close logic.
Returns
trueif the socket is open.falseif it is closed or has encountered a fatal error.
Example
ws:close
ws:closeCloses the WebSocket connection.
Signals the background receive thread to stop.
Sends a WebSocket close frame (best effort).
Waits for the thread to exit, then closes all WinHTTP handles.
Parameters
code : integer (optional)WebSocket close status. Defaults to
WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS.
Example
Metamethods
__gc
Called automatically when the Lua userdata is garbage collected.
Calls
ws_close_internal, deletes the critical section, freeslua_ws_t.You don’t call this directly; it’s tied to object lifetime.
__tostring
Used when you do:
Returns
"websocket(open)"or"websocket(closed)".
Example:
Summary
Global HTTP:
Global WebSocket:
WebSocket object (net_ws):
Last updated