summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
authorMartin Ashby <martin@ashbysoft.com>2023-08-06 06:59:44 +0100
committerMartin Ashby <martin@ashbysoft.com>2023-08-06 06:59:44 +0100
commit95699a6ed77e1480e7b9256035225981cb33bfbb (patch)
tree4ac270c06a6e675761731ff65943a39072ff8d52 /src/main.zig
parent292e1bf1692091fa218ced45a8b49fc799a2759a (diff)
downloadzigwebserver-95699a6ed77e1480e7b9256035225981cb33bfbb.tar.gz
zigwebserver-95699a6ed77e1480e7b9256035225981cb33bfbb.tar.bz2
zigwebserver-95699a6ed77e1480e7b9256035225981cb33bfbb.tar.xz
zigwebserver-95699a6ed77e1480e7b9256035225981cb33bfbb.zip
Add path parsing, use it
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig89
1 files changed, 48 insertions, 41 deletions
diff --git a/src/main.zig b/src/main.zig
index 54e6b4b..1f4d8f9 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -2,65 +2,72 @@ const std = @import("std");
const zws = @import("zigwebserver.zig");
// 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);
+const Context = struct {
+ pub fn clone(_: Context) Context {
+ return .{};
+ }
+ pub fn deinit(_: Context) void {}
+};
+const Handler = struct {
+ pub fn handle(_: Handler, res: *std.http.Server.Response, _: Context) !void {
+ const p = try zws.Path.parse(res.request.target);
+ const path = try std.fs.path.join(res.allocator, &[_][]const u8{ ".", p.path });
+ defer res.allocator.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);
+ const index_path = try std.fs.path.join(res.allocator, &[_][]const u8{ path, "index.html" });
+ defer res.allocator.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);
+ try serve_file(res, index_file, index_md);
} else |_| {
- try serve_error(&res, .not_found);
+ try serve_error(res, .not_found);
}
} else {
- try serve_file(&res, file, md);
+ 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),
+ 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_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;
- res.transfer_encoding = .chunked;
- try res.do();
- const phrase = status.phrase() orelse "error!";
- try std.fmt.format(res.writer(),
- \\ <!doctype html><html><body>{s}</body></html>
- , .{phrase});
+ fn serve_error(res: *std.http.Server.Response, status: std.http.Status) !void {
+ res.status = status;
+ res.transfer_encoding = .chunked;
+ try res.do();
+ const phrase = status.phrase() orelse "error!";
+ try std.fmt.format(res.writer(),
+ \\ <!doctype html><html><body>{s}</body></html>
+ , .{phrase});
+ }
+};
+const Server = zws.Server(Context, Handler);
+var allocator = std.heap.GeneralPurposeAllocator(.{}){};
+var svr = Server{
+ .allocator = allocator.allocator(),
+ .address = std.net.Address{ .in = std.net.Ip4Address.init(.{ 127, 0, 0, 1 }, 8080) },
+ .context = Context{},
+ .handler = Handler{},
+};
+
+pub fn main() !void {
+ try svr.serve();
}
test {