Backend
zig-http
Zig HTTP 网络编程技能。涉及 std.http 的客户端请求、服务端实现、WebSocket、TLS、连接池和压缩。在需要发起 HTTP 请求或搭建 HTTP 服务端时调用。
Zig HTTP 网络编程技能。涉及 std.http 的客户端请求、服务端实现、WebSocket、TLS、连接池和压缩。在需要发起 HTTP 请求或搭建 HTTP 服务端时调用。
基于 std.http 的客户端与服务端开发(Zig 0.16.0)。
zig version)zig-0.16 的 std.netzig-0.16 技能本技能不收集、存储或传输任何用户数据。
步骤 1. 初始化 Client — std.http.Client{ .allocator = allocator }
步骤 2. 配置请求 — URL、方法、头、请求体
步骤 3. 发送请求 — client.fetch() 或底层 API
步骤 4. 处理响应 — 状态码、响应体
步骤 5. 资源清理 — client.deinit()
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)});
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});
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" },
},
});
var uri = std.Uri.parse("https://api.example.com/search")?;
uri.query = "q=zig&limit=10";
const result = try client.fetch(.{ .location = .{ .uri = uri } });
const result = try client.fetch(.{
.location = .{ .url = "https://api.example.com/protected" },
.headers = &.{
.{ .name = "Authorization", .value = "Bearer token123" },
.{ .name = "Accept", .value = "application/json" },
},
});
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,
});
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);
try client.pool.enable(); // 启用连接池
// 多个请求复用连接
for (urls) |url| {
const result = try client.fetch(.{ .location = .{ .url = url } });
_ = result;
}
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", .{});
}
}
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 });
}
}
const body = "{\"name\": \"server\", \"version\": \"1.0\"}";
try req.respond(body, .{ .content_type = .json });
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
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);
}
client.deinit() 释放连接池和资源fetch() 默认不限制大小,但自行提供固定 buffer 时注意溢出server.ca_bundle127.0.0.1,IPv6 用 [::1]Q:如何设置超时?
A:使用底层 API(client.request + req.wait())可以控制超时。fetch() 高层 API 暂不支持超时。
Q:最大并发连接数? A:默认 128。启用连接池后自动管理复用,不显式限制。
Q:支持 HTTP/2 吗? A:std.http 目前仅支持 HTTP/1.1。HTTP/2 支持计划中。