Simple HTTP fetch request

Hi friends, I am relatively new to the Zig programming language. I am trying to write a program that uses an external API that I want to call in my program. I have already tried different ways to do this, but I am really confused with the httpclient, fetchoptions, requestoptions. Can someone give me a brief introduction to the http std lib and how to retrieve an API?
Thank you very much

Edit: Changed title

Hi @chrischtel Welcome to ziggit :slight_smile:

The http client documentation really needs an example.
Here is a simple one that searches google:

const std = @import("std");

pub fn main() !void {
    // Create a general purpose allocator
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();

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

    // Allocate a buffer for server headers
    var buf: [4096]u8 = undefined;

    // Start the HTTP request
    const uri = try std.Uri.parse("https://www.google.com?q=zig");
    var req = try client.open(.GET, uri, .{ .server_header_buffer = &buf });
    defer req.deinit();

    // Send the HTTP request headers
    try req.send();
    // Finish the body of a request
    try req.finish();

    // Waits for a response from the server and parses any headers that are sent
    try req.wait();

    std.debug.print("status={d}\n", .{req.response.status});
}
4 Likes

hi @dimdin, thank you! I really love zig but the lack of documentation makes it hard for noobies like me to learn the language. But I think I slowly get used to it and that’s why we have this community!

2 Likes

There is a lot of good documentation on the language. On the standard library, less so… (And specially for std.http.)

I thought so too at first. Now I actually think this is a good thing - it forces you to read and dig through source code. And that is a valuable skill to develop IMHO. But, I also think that the whole networking stuff in Zig has relatively less documentation compared to say std.fs. Might be that’s because it came in more recently into std.

By the way, the Zig CC has two http examples in the Zig cookbook. There’s also a section on TCP.

2 Likes

To complete the answer given by @dimdin here is code which also reads and displays the HTTP response headers and body:

// Zig example of the use of the standard library HTTP client
// <https://ziglang.org/documentation/0.12.0/std/#std.http.Client> We
// retrieve JSON data from a network API. We are not very paranoid,
// more checks should be created.

const std = @import("std");

// The API we use
const ref_url = "https://api.coindesk.com/v1/bpi/currentprice.json";

// Some values
const headers_max_size = 1024;
const body_max_size = 65536;

pub fn main() !void {
    const url = try std.Uri.parse(ref_url);

    // We need an allocator to create a std.http.Client
    var gpa_impl = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa_impl.deinit();
    const gpa = gpa_impl.allocator();

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

    var hbuffer: [headers_max_size]u8 = undefined;
    const options = std.http.Client.RequestOptions{ .server_header_buffer = &hbuffer };

    // Call the API endpoint
    var request = try client.open(std.http.Method.GET, url, options);
    defer request.deinit();
    _ = try request.send();
    _ = try request.finish();
    _ = try request.wait();

    // Check the HTTP return code
    if (request.response.status != std.http.Status.ok) {
        return error.WrongStatusResponse;
    }

    // Read the body
    var bbuffer: [body_max_size]u8 = undefined;
    const hlength = request.response.parser.header_bytes_len;
    _ = try request.readAll(&bbuffer);
    const blength = request.response.content_length orelse return error.NoBodyLength; // We trust
    // the Content-Length returned by the server…

    // Display the result
    std.debug.print("{d} header bytes returned:\n{s}\n", .{ hlength, hbuffer[0..hlength] });
    // The response is in JSON so we should here add JSON parsing code.
    std.debug.print("{d} body bytes returned:\n{s}\n", .{ blength, bbuffer[0..blength] });
}
2 Likes

Thanks for referencing the Zig CC. i didn’t know that it exists, I think it will help me a lot. Thank you!

Christian