]> jxnshi.xyz Git - jxnshi.xyz.git/commitdiff
Add file routing
authorjxnshi <jxnshi@cock.li>
Sat, 7 Dec 2024 23:29:57 +0000 (00:29 +0100)
committerjxnshi <jxnshi@cock.li>
Sat, 7 Dec 2024 23:29:57 +0000 (00:29 +0100)
public/layout.html [moved from public/layouts/main.html with 100% similarity]
src/main.zig

similarity index 100%
rename from public/layouts/main.html
rename to public/layout.html
index ac5f668e02efd58bd654355b7ac1e60ac47ae7e3..a0e10de186278e755dc89430a4b42f538562b334 100644 (file)
@@ -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();
     }
 }