From 67d4e59170fc57fdb720683ff8a78925b32fffbe Mon Sep 17 00:00:00 2001 From: jxnshi Date: Sun, 8 Dec 2024 00:29:57 +0100 Subject: [PATCH] Add file routing --- public/{layouts/main.html => layout.html} | 0 src/main.zig | 105 ++++++++++++++++++++-- 2 files changed, 99 insertions(+), 6 deletions(-) rename public/{layouts/main.html => layout.html} (100%) diff --git a/public/layouts/main.html b/public/layout.html similarity index 100% rename from public/layouts/main.html rename to public/layout.html diff --git a/src/main.zig b/src/main.zig index ac5f668..a0e10de 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,9 +1,93 @@ const std = @import("std"); +var fixed_allocator: std.heap.FixedBufferAllocator = undefined; var allocator: std.mem.Allocator = undefined; +fn parentDirPath(path: []const u8) ?[]const u8 { + for (0..path.len) |idx| { + const i = path.len - idx - 1; + const char = path[i]; + + if (char == '/') { + return path[0..i]; + } + } +} + fn handleClient(connection: std.net.Server.Connection) !void { - // + var read_buffer: [4_096]u8 = undefined; + + var server = std.http.Server.init(connection, &read_buffer); + + const cwd = std.fs.cwd(); + + var public_dir = try cwd.openDir("public", .{}); + defer public_dir.close(); + + while (true) { + defer fixed_allocator.reset(); + + var send_buffer = std.ArrayList(u8).init(allocator); + defer send_buffer.deinit(); + + var request = try server.receiveHead(); + + const target = request.head.target; + const route = target[1..]; + + std.log.info("Received request to {s}.", .{target}); + + const is_file = blk: { + const stat = public_dir.statFile(route) catch break :blk false; + break :blk stat.kind == .file; + }; + + if (is_file) blk: { + const file = public_dir.openFile(route, .{}) catch |err| { + std.log.err("Could not open file \"{s}\" with error {}", .{ route, err }); + break :blk; + }; + + defer file.close(); + + const file_reader = file.reader(); + try file_reader.readAllArrayList(&send_buffer, std.math.maxInt(usize)); + } else { + var maybe_index_file: ?std.fs.File = null; + + index_file: { + blk: { + var route_dir = public_dir.openDir(route, .{}) catch break :blk; + defer route_dir.close(); + + maybe_index_file = route_dir.openFile("index.html", .{}) catch break :blk; + + break :index_file; + } + + var path_ext = std.ArrayList(u8).init(allocator); + defer path_ext.deinit(); + + try path_ext.appendSlice(route); + try path_ext.appendSlice(".html"); + + if (public_dir.openFile(route, .{})) |index_file| { + maybe_index_file = index_file; + } else |_| { + // + } + } + + if (maybe_index_file) |index_file| { + defer index_file.close(); + + const index_file_reader = index_file.reader(); + try index_file_reader.readAllArrayList(&send_buffer, std.math.maxInt(usize)); + } + } + + try request.respond(send_buffer.items, .{}); + } } fn handleClientThread(connection: std.net.Server.Connection) void { @@ -11,19 +95,28 @@ fn handleClientThread(connection: std.net.Server.Connection) void { } pub fn main() !void { - var buffer: [32_768]u8 = undefined; - var fixed_allocator = std.heap.FixedBufferAllocator.init(&buffer); + var buffer: [65_536]u8 = undefined; + fixed_allocator = std.heap.FixedBufferAllocator.init(&buffer); allocator = fixed_allocator.allocator(); - const server_addr = try std.net.Address.parseIp4(&.{ 0, 0, 0, 0 }, 3000); + const server_addr = try std.net.Address.parseIp("0.0.0.0", 3000); + + var server = try server_addr.listen(.{ + .reuse_address = true, + .reuse_port = true, + }); - var server = try server_addr.listen(.{}); defer server.deinit(); + std.log.info("Server lisening.", .{}); + while (true) { const connection = try server.accept(); - std.Thread.spawn(.{}, handleClientThread, .{connection}); + std.log.info("Connection from {}.", .{connection.address}); + + const thread = try std.Thread.spawn(.{}, handleClientThread, .{connection}); + thread.detach(); } } -- 2.49.0