std.net.http_client

http_client performs requests via request() and returns the full response. Reuse the same client for multiple requests — default headers persist until cleared. Each request() opens its own connection (close-per-request), so sharing one client across spawned fibers is safe; concurrent requests simply run as independent connections.

Basic request

var c = std.net.http_client()
c.set_header("Authorization", "Bearer abc123")

var r = c.request({
  url: "http://127.0.0.1:8200/api",
  method: "POST",                            # any verb string: GET, PUT, DELETE, …
  headers: {"content-type": "application/json"},
  body: std.json.stringify({name: "scrii"})
})

print(r.status)                              # 200 (int)
print(r.status_line)                         # HTTP/1.1 200 OK
print(r.body)                                # response body as string
print(r.headers["Content-Type"])             # per-response headers (capitalized keys)
print(r.raw_headers)                         # raw header block as string

if (r.status == std.net.http_codes.ok) {
  print("success:", r.body)
}

Request options

Key Purpose
url Full URL (http:// or https://host:port/path?query)
method HTTP verb string (default "GET")
headers Per-request header object
body Request body string
verify For https://: false disables certificate verification (self-signed). Default true
timeout_ms Send/receive timeout in milliseconds; a stalled server cannot hang the request forever. Default: no timeout

method is any string — GET, POST, PUT, PATCH, DELETE, etc. body is sent as-is; stringify JSON yourself with std.json.stringify.

Redirects

3xx responses with a Location header are followed automatically, up to 5 hops. 303 (and 301/302 on POST bodies) demote to GET and drop the body, per common practice. The final non-redirect response is returned.

Disconnect hook

on_disconnect(fn({url, error})) fires when a request’s connection drops mid-flight (send failure, EOF before/during the body). The request still throws — a throwing hook is reported on stderr without masking the original failure. Clean completions and connect-time failures do not fire it:

c.on_disconnect(fn(info) {
  print("lost", info.url, "-", info.error)
})

Headers

c.set_header("X-Token", "abc")   # default header for every future request
c.set_header("X-Token", "def")   # overwrites
c.clear_headers()                # remove all defaults before next request
  • set_header(name, value) / clear_headers() manage default request headers that are sent on every request().
  • Per-request headers in the request() object are merged on top of defaults for that single call.
  • Response r.headers uses capitalized keys (Content-Type, Content-Length, Connection). Access as r.headers["Content-Type"].
  • r.raw_headers is the raw header block as a single string — useful for debugging.

Parallel fetching

Combine with Concurrency to fetch several URLs in parallel:

var urls = ["http://127.0.0.1:8200/a", "http://127.0.0.1:8200/b"]
var futures = []
for (u : urls) {
  futures:insert(std.async.spawn(fn(u) {
    return std.net.http_client().request({url: u}).body
  }, u))
}
for (f : futures) { print(std.async.await(f)) } # all fetches overlapped

TLS

https:// works when the engine is built with OpenSSL (see Overview). Certificate verification is on by default; pass verify: false in the request object to trust self-signed servers. Without OpenSSL, https:// throws UNSUPPORTED.

var r = c.request({url: "https://127.0.0.1:8443/api", verify: false})

See also

  • HTTP Server — serve the same routes you request
  • URL — parse URLs before requesting
  • DNS — resolve hostnames manually
  • Overview — http_codes table