SuperAPI AI Directory

zig-http

Coding & development

View repository

Updated 10-15 21:48

About this skill

Zig HTTP Network Programming

Client and server development based on std.http (Zig 0.16.0).

Capability Boundaries

✅ Strengths

  1. HTTP client requests (GET/POST/PUT/DELETE)
  2. Custom request headers, request bodies, query parameters
  3. HTTP server setup and routing
  4. WebSocket client and server
  5. TLS/HTTPS connections
  6. Connection pool management and compression

⚠️ Prerequisites

  1. Confirm the Zig version (zig version)
  2. For HTTPS, the system needs CA certificates

❌ Out of Scope

  1. Non-HTTP network programming → use zig-0.16 's std.net
  2. Zig language fundamentals → use the zig-0.16 skill

When to Use

  • "Help me write an HTTP client"
  • "How do I set up an HTTP server?"
  • "Call a REST API with Zig"

Data Privacy

This skill does not collect, store, or transmit any user data.

Workflow

Step 1. Initialize Client — std.http.Client{ .allocator = allocator } Step 2. Configure the request — URL, method, headers, request body Step 3. Send the request — client.fetch() or the low-level API Step 4. Handle the response — status code, response body Step 5. Resource cleanup — client.deinit()

HTTP Client

Quick GET

var client: std.http.Client = .{ .allocator = allocator };
defer client.deinit();

const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/data" },
});
std.debug.print("Status: {d}\n", .{@intFromEnum(result.status)});

GET and read the response body

var body_buf: [65536]u8 = undefined;
var body_writer: std.Io.Writer = .fixed(&body_buf);

const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/data" },
    .response_writer = &body_writer,
});
const body = body_writer.buffered();
std.debug.print("Body: {s}\n", .{body});

POST JSON

const payload = "{\"key\": \"value\"}";
var buf: [4096]u8 = undefined;
var body_writer: std.Io.Writer = .fixed(&buf);

const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/submit" },
    .method = .POST,
    .payload = payload,
    .response_writer = &body_writer,
    .headers = &.{
        .{ .name = "Content-Type", .value = "application/json" },
    },
});

With query parameters

var uri = std.Uri.parse("https://api.example.com/search")?;
uri.query = "q=zig&limit=10";

const result = try client.fetch(.{ .location = .{ .uri = uri } });

Custom request headers

const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/protected" },
    .headers = &.{
        .{ .name = "Authorization", .value = "Bearer token123" },
        .{ .name = "Accept", .value = "application/json" },
    },
});

File upload (multipart)

var form = std.http.Client.Fetch.Form.init(allocator);
defer form.deinit();
try form.field("name", "value");
try form.field("file", file_contents, .{ .filename = "data.txt" });

const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/upload" },
    .method = .POST,
    .form = form,
});

Low-level request (finer-grained control)

var req = try client.request(.GET, uri, .{}, .{});
defer req.deinit();

// 发送请求头
try req.send(.{});

// 发送请求体(可选)
try req.writeAll("body data");

// 开始读取响应
try req.finish();
try req.wait();

// 读取响应体
var buf: [4096]u8 = undefined;
var reader_writer: std.Io.Writer = .fixed(&buf);
try req.reader().?.readAllWriter(&reader_writer);

Connection pool

try client.pool.enable();  // 启用连接池
// 多个请求复用连接
for (urls) |url| {
    const result = try client.fetch(.{ .location = .{ .url = url } });
    _ = result;
}

HTTP Server

Basic server

pub fn main() !void {
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var server = std.http.Server.init(allocator, .{
        .reuse_port = true,
    });
    defer server.deinit();

    const addr = try std.net.Address.parseIp("127.0.0.1", 8080);
    try server.listen(addr);

    while (true) {
        var response_buf: [65536]u8 = undefined;
        var req = try server.accept(.{ .response_buffer = &response_buf });
        defer req.deinit();

        // 响应 Hello World
        try req.respond("Hello, World!\n", .{});
    }
}

Route dispatch

while (true) {
    var buf: [65536]u8 = undefined;
    var req = try server.accept(.{ .response_buffer = &buf });
    defer req.deinit();

    const url = req.request.target;
    if (std.mem.eql(u8, url, "/api/hello")) {
        try req.respond("{\"msg\": \"hello\"}", .{ .content_type = .json });
    } else if (std.mem.eql(u8, url, "/api/status")) {
        try req.respond("{\"status\": \"ok\"}", .{ .content_type = .json });
    } else {
        try req.respond("Not Found", .{ .status = .not_found });
    }
}

JSON response

const body = "{\"name\": \"server\", \"version\": \"1.0\"}";
try req.respond(body, .{ .content_type = .json });

Read the request body

var req_body: [4096]u8 = undefined;
const body_len = try req.readAll(&req_body);
const body = req_body[0..body_len];
// 处理 body...
try req.respond("OK", .{});

WebSocket

// 服务端升级到 WebSocket
var ws = try req.upgradeToWebSocket(.{});
defer ws.deinit();

while (true) {
    const frame = try ws.readFrame() orelse break;
    std.debug.print("Received: {s}\n", .{frame.payload});
    try ws.writeFrame("echo: " ++ frame.payload);
}

Gotchas

  1. std.http is experimental in 0.16 — the API may change in future versions
  2. Client must be deinit'ed — client.deinit() to release the connection pool and resources
  3. Response body size limit — fetch() By default there is no size limit, but be careful of overflow when providing your own fixed buffer
  4. HTTPS requires system CAs — in containers or environments without CAs, you may need to configure server.ca_bundle
  5. Server.listen's addr — use 127.0.0.1for IPv4, [::1]

FAQ

Q: How do I set a timeout? A: Use the low-level API (client.request + req.wait()) to control timeouts.fetch() The high-level API does not currently support timeouts.

Q: Maximum number of concurrent connections? A: 128 by default. Once the connection pool is enabled, reuse is managed automatically, with no explicit limit.

Q: Is HTTP/2 supported? A: std.http currently only supports HTTP/1.1. HTTP/2 support is planned.