As you can see with simple fetch() we need to provide std.Io.Writer where response body is supposed to be written. Sometimes we need std.Io.Reader instead in which case we need to copy what fetch does and do it ourselves instead.
Here is more involved example which fetches list of zig compiler versions and prints it in console.
const std = @import("std");
const Schema = std.json.ArrayHashMap(struct {
version: ?[]const u8 = null,
date: []const u8,
docs: []const u8,
stdDocs: ?[]const u8 = null,
src: struct {
tarball: []const u8,
shasum: []const u8,
size: []const u8,
},
});
pub fn main() !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
var client: std.http.Client = .{
.allocator = gpa.allocator(),
};
defer client.deinit();
var req = try client.request(.GET, try .parse("https://ziglang.org/download/index.json"), .{});
defer req.deinit();
try req.sendBodiless();
var response = try req.receiveHead(&.{});
var decompress_buffer: [std.compress.flate.max_window_len]u8 = undefined;
var transfer_buffer: [64]u8 = undefined;
var decompress: std.http.Decompress = undefined;
const decompressed_body_reader = response.readerDecompressing(&transfer_buffer, &decompress, &decompress_buffer);
var json_reader: std.json.Reader = .init(gpa.allocator(), decompressed_body_reader);
defer json_reader.deinit();
const result: std.json.Parsed(Schema) = try std.json.parseFromTokenSource(Schema, gpa.allocator(), &json_reader, .{
.ignore_unknown_fields = true,
});
defer result.deinit();
if (response.head.status.class() == .success) {
var stdout_buffer: [0x100]u8 = undefined;
var stdout = std.fs.File.stdout().writer(&stdout_buffer);
for (result.value.map.keys()) |version| {
try stdout.interface.print("{s}\n", .{version});
}
try stdout.interface.flush();
} else {
std.log.err("request failed: {?s}", .{response.head.status.phrase()});
}
}