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 {
}
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();
}
}