diff options
author | Martin Ashby <martin@ashbysoft.com> | 2023-07-18 13:32:04 +0000 |
---|---|---|
committer | Martin Ashby <martin@ashbysoft.com> | 2023-07-18 13:32:04 +0000 |
commit | 47214a1b045ed8aac7166828bf67dea2769148f0 (patch) | |
tree | 0660feeec2d04aaa16887bf08c0af9dbf3b72e45 /src | |
download | zigwebserver-47214a1b045ed8aac7166828bf67dea2769148f0.tar.gz zigwebserver-47214a1b045ed8aac7166828bf67dea2769148f0.tar.bz2 zigwebserver-47214a1b045ed8aac7166828bf67dea2769148f0.tar.xz zigwebserver-47214a1b045ed8aac7166828bf67dea2769148f0.zip |
enough of a web server to host the zig docs
Diffstat (limited to 'src')
-rw-r--r-- | src/main.zig | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..335e80c --- /dev/null +++ b/src/main.zig @@ -0,0 +1,63 @@ +const std = @import("std"); + +// extremely basic http file server +pub fn main() !void { + var allocator = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = allocator.deinit(); + const alloc = allocator.allocator(); + var svr = std.http.Server.init(alloc, .{.reuse_address = true}); + defer svr.deinit(); + const addr = try std.net.Address.resolveIp("127.0.0.1", 8080); + + try svr.listen(addr); + while (true) { + var res = try svr.accept(.{.allocator = alloc }); + defer res.deinit(); + try res.wait(); + const target = res.request.target; + const path = try std.fs.path.join(alloc, &[_][]const u8{".", target}); + defer alloc.free(path); + if (std.fs.cwd().openFile(path, .{})) |file| { + const md = try file.metadata(); + if (md.kind() == .directory) { + const index_path = try std.fs.path.join(alloc, &[_][]const u8{path, "index.html"}); + defer alloc.free(index_path); + if (std.fs.cwd().openFile(index_path, .{})) |index_file| { + const index_md = try index_file.metadata(); + try serve_file(&res, index_file, index_md); + } else |_| { + try serve_error(&res, .not_found); + } + } else { + try serve_file(&res, file, md); + } + } else |err| { + switch (err) { + error.FileNotFound => try serve_error(&res, .not_found), + else => try serve_error(&res, .bad_request), + } + } + try res.finish(); + } +} + +fn serve_file(res: *std.http.Server.Response, file: std.fs.File, md: std.fs.File.Metadata) !void { + res.transfer_encoding = .{ .content_length = md.size() }; + try res.do(); + var buf = [_]u8{0} ** 1024; + while (true) { + const read = try file.read(&buf); + if (read == 0) break; + _ = try res.write(buf[0..read]); + } +} + +fn serve_error(res: *std.http.Server.Response, status: std.http.Status) !void { + res.status = status; + const msg = + \\ <!doctype html><html><body>error!</body></html> + ; + res.transfer_encoding = . { .content_length = msg.len }; + try res.do(); + _ = try res.write(msg); +} |