async: add pure async http client

This commit is contained in:
Pierre Tachoire
2024-01-30 09:32:20 +01:00
parent 511e9b969a
commit c200f60d7d
2 changed files with 88 additions and 1 deletions

65
src/async/http.zig Normal file
View File

@@ -0,0 +1,65 @@
const std = @import("std");
const http = std.http;
const stdcli = @import("Client.zig");
pub const Loop = @import("jsruntime").Loop;
pub const Client = struct {
cli: stdcli,
pub fn init(alloc: std.mem.Allocator, loop: *Loop) Client {
return .{ .cli = .{
.allocator = alloc,
.loop = loop,
} };
}
pub fn deinit(self: *Client) void {
self.cli.deinit();
}
pub fn create(self: *Client, uri: std.Uri) Request {
return .{
.cli = &self.cli,
.uri = uri,
.headers = .{ .allocator = self.cli.allocator, .owned = false },
};
}
};
pub const Request = struct {
cli: *stdcli,
uri: std.Uri,
headers: std.http.Headers,
done: bool = false,
err: ?anyerror = null,
pub fn deinit(self: *Request) void {
self.headers.deinit();
}
pub fn fetch(self: *Request) !void {
self.cli.loop.yield(*Request, self, callback);
}
fn onerr(self: *Request, err: anyerror) void {
self.err = err;
}
fn callback(self: *Request, err: ?anyerror) void {
if (err) |e| return self.onerr(e);
defer self.done = true;
var req = self.cli.open(.GET, self.uri, self.headers, .{}) catch |e| return self.onerr(e);
defer req.deinit();
req.send(.{}) catch |e| return self.onerr(e);
req.finish() catch |e| return self.onerr(e);
req.wait() catch |e| return self.onerr(e);
}
pub fn wait(self: *Request) !void {
while (!self.done) try self.cli.loop.tick();
if (self.err) |err| return err;
}
};

View File

@@ -1,7 +1,8 @@
const std = @import("std");
const http = std.http;
const StdClient = @import("Client.zig");
// const hasync = @import("http.zig");
const AsyncClient = @import("http.zig").Client;
const AsyncRequest = @import("http.zig").Request;
pub const Loop = @import("jsruntime").Loop;
@@ -58,3 +59,24 @@ test "blocking mode open/send/wait API" {
try std.testing.expect(req.response.status == .ok);
}
test "non blocking mode API" {
const alloc = std.testing.allocator;
var loop = try Loop.init(alloc);
defer loop.deinit();
var client = AsyncClient.init(alloc, &loop);
defer client.deinit();
var reqs: [10]AsyncRequest = undefined;
for (0..reqs.len) |i| {
reqs[i] = client.create(try std.Uri.parse(url));
try reqs[i].fetch();
}
for (0..reqs.len) |i| {
try reqs[i].wait();
reqs[i].deinit();
}
}