Simple HTTP fetch request

The API may have changed some since this was originally asked.
Here is a complete working example with comments using the latest Zig version and latest version of the standard library.
This uses a JSON API, but the fundamentals are the same regardless.

var debug_allocator: std.heap.DebugAllocator(.{}) = .init;

pub fn main() !void {
    const allocator, const is_debug = gpa: {
        break :gpa switch (builtin.mode) {
            .Debug, .ReleaseSafe => .{ debug_allocator.allocator(), true },
            .ReleaseFast, .ReleaseSmall => .{ std.heap.smp_allocator, false },
        };
    };
    defer if (is_debug) {
        _ = debug_allocator.deinit();
    };

    // Create the client
    var client = std.http.Client{ .allocator = allocator };
    defer client.deinit();

    // Initialize an array list that we will use for storage of the response body
    var body = std.ArrayList(u8).init(allocator);
    defer body.deinit();

    // Parse a URI. Conversely the "location" field below will also
    // accept a URL string, but using URI here for clarity.
    const uri = try std.Uri.parse("https://api.quotable.kurokeita.dev/api/quotes/random");

    // Make the request
    const response = try client.fetch(.{
        .method = .GET,
        .location = .{ .uri = uri },
        .response_storage = .{ .dynamic = &body },
        .headers = .{
            .accept_encoding = .{ .override = "application/json" },
        },
    });

    // Do whatever you need to in case of HTTP error.
    if (response.status != .ok) {
        @panic("Handle errors");
    }

    // This is the struct used to describe the JSON response
    // technically there could be error responses and error messages in this struct,
    // but that is beyond the cope of this example
    const QuoteResponse = struct {
        quote: struct {
            author: struct {
                bio: []u8,
                description: []u8,
                id: []u8,
                link: []u8,
                name: []u8,
                slug: []u8,
            },
            content: []u8,
            id: []u8,
            tags: []struct {
                id: []u8,
                name: []u8,
            },
        },
    };

    // Parse the reply into a struct
    const parsed = try std.json.parseFromSlice(QuoteResponse, allocator, body.items, .{
        .allocate = .alloc_always,
        .parse_numbers = true,
        .ignore_unknown_fields = true,
    });
    defer parsed.deinit();

    // Print the output
    const quote = parsed.value.quote;
    var stdout = std.io.getStdOut();
    var writer = stdout.writer();
    try writer.print("\"{s}\"\n\n- {s}", .{ quote.content, quote.author.name });
}

const std = @import("std");
const builtin = @import("builtin");

The API definition can be found here if you need it.

2 Likes