diff --git a/src/async/http.zig b/src/async/http.zig new file mode 100644 index 00000000..1a631959 --- /dev/null +++ b/src/async/http.zig @@ -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; + } +}; diff --git a/src/async/test.zig b/src/async/test.zig index 10081e9e..d5262d06 100644 --- a/src/async/test.zig +++ b/src/async/test.zig @@ -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(); + } +}