Zig POSIX HTTP JSON fetch with deadline
Zig
const std = @import("std");
fn getJson(alloc: std.mem.Allocator, host: []const u8, path: []const u8, timeout_ms: u64) !std.json.Parsed(std.json.Value) {
const stream = try std.net.tcpConnectToHost(alloc, host, 80);
defer stream.close();
try stream.writer().print("GET {s} HTTP/1.0\r\nHost: {s}\r\nAccept: application/json\r\n\r\n", .{ path, host });
var timer = try std.time.Timer.start();
var fds = [_]std.posix.pollfd{.{ .fd = stream.handle, .events = std.posix.POLL.IN, .revents = 0 }};
var raw = std.ArrayList(u8).init(alloc); defer raw.deinit();
while (true) {
const left = timeout_ms -| (timer.read() / std.time.ns_per_ms);
if (left == 0) return error.Timeout;
if (try std.posix.poll(&fds, @intCast(left)) == 0) return error.Timeout;
var buf: [4096]u8 = undefined;
const n = try stream.read(&buf);
if (n == 0) break;
try raw.appendSlice(buf[0..n]);
}
if (!std.mem.startsWith(u8, raw.items, "HTTP/1.0 200") and !std.mem.startsWith(u8, raw.items, "HTTP/1.1 200")) return error.HttpStatus;
const body = raw.items[std.mem.indexOf(u8, raw.items, "\r\n\r\n").? + 4 ..];
return std.json.parseFromSlice(std.json.Value, alloc, body, .{ .allocate = .alloc_always });
}