diff options
| author | Robert Günzler <r@gnzler.io> | 2026-09-29 10:32:19 +0200 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2026-10-02 10:39:48 +0200 |
| commit | 5d595d877b48fd77f691d5401206abc8e2fcca1d (patch) | |
| tree | fad1cf8f1a3d9069de424cec356c5575a26d7ae6 | |
| parent | 5f4ef02e69e0ca2df85144e0824a167642d956d5 (diff) | |
| download | site-5d595d877b48fd77f691d5401206abc8e2fcca1d.tar.gz | |
server: make concurrent
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to '')
| -rw-r--r-- | src/main.zig | 97 |
1 files changed, 67 insertions, 30 deletions
diff --git a/src/main.zig b/src/main.zig index 4a87c86..642cb7a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -477,46 +477,83 @@ const Cli = struct { log.info("Serving root={s} addr={s}", .{ root_path, addrStr }); - const serverNode = if (!DEBUG) progress.start(addrStr, 0); + const server_node = if (!DEBUG) progress.start(addrStr, 0); defer if (!DEBUG) progress.end(); // tcp server var server = try addr.listen(io, .{ .reuse_address = true }); defer server.deinit(io); + var group: Io.Group = .init; + defer group.cancel(io); + while (true) { const stream = try server.accept(io); - defer stream.close(io); - - var stream_read_buffer: [BUFFER_SIZE]u8 = undefined; - var stream_reader = stream.reader(io, &stream_read_buffer); - var stream_write_buffer: [BUFFER_SIZE]u8 = undefined; - var stream_writer = stream.writer(io, &stream_write_buffer); - - var http_server = std.http.Server.init(&stream_reader.interface, &stream_writer.interface); - var req = try http_server.receiveHead(); - - log.info("{s} {s}", .{ @tagName(req.head.method), req.head.target }); - - const streamNode = if (!DEBUG) serverNode.start(req.head.target, 0); - defer if (!DEBUG) streamNode.end(); - - switch (req.head.method) { - .GET, .HEAD => {}, - else => return, - } - - var fd = File.init(io, root_dir, req.head.target[1..], null) catch |err| { - switch (err) { - error.FileNotFound => try req.respond("", .{ .status = .not_found }), - else => try req.respond("", .{ .status = .internal_server_error }), - } - continue; - }; - defer fd.close(io); + errdefer stream.close(io); - try req.respond(fd.mmap.memory, .{ .status = .ok }); + try group.concurrent( + io, + struct { + fn inner( + io_: Io, + stream_: Io.net.Stream, + root_dir_: Dir, + server_node_: ?std.Progress.Node, + ) error{Canceled}!void { + var rbuffer: [BUFFER_SIZE]u8 = undefined; + var r = stream_.reader(io_, &rbuffer); + var wbuffer: [BUFFER_SIZE]u8 = undefined; + var w = stream_.writer(io_, &wbuffer); + var http_server = std.http.Server.init(&r.interface, &w.interface); + while (true) { + var req: std.http.Server.Request = undefined; + (blk: { + req = http_server.receiveHead() catch |err| switch (err) { + error.HttpConnectionClosing => return, // return from the connection handler + error.ReadFailed => return, + else => { + log.err("ctx=recv", .{}); + break :blk err; + }, + }; + + log.info("{s} {s}", .{ @tagName(req.head.method), req.head.target }); + + const stream_node = if (!DEBUG) server_node_.?.start(req.head.target, 0); + defer if (!DEBUG) stream_node.end(); + + switch (req.head.method) { + .GET, .HEAD => {}, + else => return, + } + + var fd = File.init(io_, root_dir_, req.head.target[1..], null) catch |err| { + return switch (err) { + error.FileNotFound => break :blk req.respond("", .{ .status = .not_found }), + else => { + log.err("ctx=file", .{}); + break :blk err; + }, + }; + }; + defer fd.close(io_); + + req.respond(fd.mmap.memory, .{ .status = .ok }) catch |err| { + log.err("ctx=send", .{}); + break :blk err; + }; + }) catch |err| { + log.err("target={s} {}", .{ req.head.target, err }); + return error.Canceled; + }; + } + } + }.inner, + .{ io, stream, root_dir, if (!DEBUG) server_node else null }, + ); } + + try group.await(io); } }; |