📖

ZigでHTTPリクエストを送る

2023/10/28に公開

tl;dr

const std = @import("std");
const stdin = std.io.getStdIn();
const stdout = std.io.getStdOut();

pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const allocator = arena.allocator();

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

    const uri = std.Uri.parse("https://catfact.ninja/fact") catch unreachable;

    var req = try client.request(.GET, uri, .{ .allocator = allocator }, .{});
    defer req.deinit();

    try req.start();
    try req.wait();

    const body = req.reader().readAllAlloc(allocator, 8 * 1024) catch unreachable;
    defer allocator.free(body);

    try stdout.writer().print("{s}\n", .{body});
}

前提

$ zig version
0.11.0

解説

おおよその手順は以下の4つです。

  1. Allocatorの準備
  2. リクエストの準備
  3. リクエストを実行
  4. レスポンスを取得

1. Allocatorの準備

お好みのAllocatorをどうぞ。今回はArenaAllocatorで初期化しました。

var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();

Allocatorについて詳しく知りたい方は以下の記事がおすすめです。

https://zenn.dev/0kate/articles/a9a0b0109c7fe0

2. リクエストの準備

const uri = std.Uri.parse("https://catfact.ninja/fact") catch unreachable;

var req = try client.request(.GET, uri, .{ .allocator = allocator }, .{});
defer req.deinit();

3. リクエストを実行

req.startでリクエストが実行されます。

req.waitでリクエストの終了を待ちます。

try req.start();
try req.wait();

たとえば複数のリクエストを同時に飛ばす場合は下記のように書けます。

    // var reqs: [10]std.http.Client.Request
    
    for (reqs, 0..) |_, i| {
        try reqs[i].start();
    }

    for (reqs, 0..) |_, i| {
        try reqs[i].wait();
    }

4. レスポンスを取得

readAllAllocの第二引数には割り当てるメモリのMAXサイズを指定します。

MAXサイズを超えた場合はエラーになります。

const body = req.reader().readAllAlloc(allocator, 8 * 1024) catch unreachable;
defer allocator.free(body);

さいごに

zigたのしい

Discussion