Acquis 10 - Network

This acquis is currently only available on unstable builds and its contents may change at any time.

The network library provides TCP, UDP, and HTTP/HTTPS networking with native SSL support. It integrates with the event loop for non-blocking I/O in detached coroutines.

HTTP requests

Use network.fetch for HTTP and HTTPS requests:

local status, body, headers = network.fetch("https://httpbin.org/get")
print(status)  -- 200
print(#body)   -- response size
print(headers["content-type"])  -- "application/json"

POST requests

Pass method, headers, and body as additional arguments:

local status, body = network.fetch(
  "https://httpbin.org/post",
  "POST",
  {["Content-Type"] = "application/json"},
  '{"name": "Lus"}'
)

Error handling

Network errors raise Lua errors:

local ok, err = catch network.fetch("https://invalid.host.example")
if not ok then
  print("Request failed:", err)
end

TCP connections

Client connections

Connect to a TCP server and exchange data:

local sock = network.tcp.connect("example.com", 80)
sock:settimeout(5)  -- 5 second timeout

sock:send("GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
local response = sock:receive("*a")  -- receive until EOF
sock:close()

Receive patterns

The receive method supports several patterns:

-- Receive exactly N bytes
local data = sock:receive(1024)

-- Receive a line (strips trailing newline)
local line = sock:receive("*l")

-- Receive all data until EOF
local all = sock:receive("*a")

TCP servers

Create a listening server:

local server = network.tcp.bind("127.0.0.1", 8080)
server:settimeout(10)

local client = server:accept()
client:settimeout(5)

local request = client:receive("*l")
client:send("HTTP/1.0 200 OK\r\n\r\nHello!\n")
client:close()

server:close()

UDP sockets

Create, send, and receive datagrams:

-- Sender
local sender = network.udp.open()
sender:sendto("Hello UDP", "127.0.0.1", 9000)
sender:close()

-- Receiver (bound to port)
local receiver = network.udp.open(9000, "127.0.0.1")
local data, addr, port = receiver:receive()
print(data, addr, port)  -- "Hello UDP", "127.0.0.1", sender_port
receiver:close()

Async I/O with event loop

Network operations become non-blocking in detached coroutines:

local co = coroutine.create(function()
  -- These yield when they would block
  local s1, body1 = network.fetch("https://api.example.com/data1")
  local s2, body2 = network.fetch("https://api.example.com/data2")
  return s1, s2
end)

coroutine.detach(co)
local ok, status1, status2 = coroutine.resume(co)

Async TCP example

local co = coroutine.create(function()
  local sock = network.tcp.connect("example.com", 80)
  sock:settimeout(5)
  
  sock:send("GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
  local response = sock:receive("*a")  -- yields, doesn't block
  sock:close()
  
  return #response
end)

coroutine.detach(co)
local ok, size = coroutine.resume(co)
print("Received", size, "bytes")

Socket methods

TCP client socket

MethodDescription
send(data)Send data, returns bytes sent
receive([pattern])Receive data (default: "*l")
settimeout(seconds)Set operation timeout
close()Close the connection

TCP server

MethodDescription
accept()Accept a client connection
settimeout(seconds)Set accept timeout
close()Stop listening

UDP socket

MethodDescription
sendto(data, addr, port)Send datagram
receive([size])Receive datagram (default: 8192)
setsockname(addr, port)Bind to address and port
close()Close the socket

Motivation

Lus provides native networking without external dependencies. The library handles platform differences and integrates with the event loop for modern async patterns.

Single-call HTTP

Compare to using raw sockets:

-- Without network.fetch: 20+ lines of socket, TLS, HTTP parsing
-- With network.fetch:
local status, body = network.fetch("https://api.example.com/data")

Transparent async

I/O automatically becomes non-blocking in detached coroutines:

-- Same code works sync and async
local status = network.fetch(url)

-- In detached coroutine: yields during I/O
-- In regular code: blocks until complete

Cross-platform consistency

The library handles platform-specific socket APIs (Winsock vs POSIX) and TLS configuration transparently.