summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
authorzachir <zachir@librem.one>2024-03-26 00:53:38 -0500
committerzachir <zachir@librem.one>2024-03-26 00:53:38 -0500
commit9a95ef74694076927d5e9ec8345a56b99c3f0845 (patch)
treefb232693399f93e0f85c208283ae4379002908d3 /src/main.zig
parente6b631584a4470ac8edd3c1898981367e2ffe4e9 (diff)
Add more clarifying comments
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/main.zig b/src/main.zig
index 1e62272..f074fde 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -43,10 +43,16 @@ const buffer_limit = 1 << 21;
/// file.stat() will return a StatError
/// file.readAll() will return a ReadError
fn readFiles(target: []const u8, buffer: []u8) !usize {
+ // fba_buffer is the maximum malloc size for this functiono, as it's using
+ // a Fixed Buffer Allocator. It needs to be able to contain file_path,
+ // which is max_path_bytes in size, twice over, because it may also get
+ // allocPrint'ed to if the provided target is a directory.
var fba_buffer: [max_path_bytes * 2]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&fba_buffer);
const allocator = fba.allocator();
+ // `target` is relative to the root of the http server; for now, it's
+ // going to assume the root (/) is the current working directory.
var file_path = try allocator.alloc(u8, max_path_bytes);
defer allocator.free(file_path);
var cwd_buffer = [_]u8{0} ** max_path_bytes;
@@ -59,6 +65,9 @@ fn readFiles(target: []const u8, buffer: []u8) !usize {
defer file.close();
var stat = try file.stat();
switch (stat.kind) {
+ // If the path is a directory, it needs to get the file at
+ // directory/index.html. This isn't technically the standard
+ // (probably), but it's the assumption I will make for now.
.directory => {
if (std.mem.endsWith(u8, target, "/")) {
file_path = try std.fmt.allocPrint(allocator, "{s}index.html", .{target});
@@ -67,9 +76,13 @@ fn readFiles(target: []const u8, buffer: []u8) !usize {
}
return readFiles(file_path, buffer);
},
+ // If it's a file then write all of the contents (up to buffer_limit
+ // bytes) into the provided arg buffer, and return the number of bytes
+ // written.
.file => {
return try file.readAll(buffer);
},
+ // Otherwise, it's an error I'm not going to handle.
else => {
return 0;
},
@@ -103,26 +116,38 @@ fn handleRequest(response: *std.http.Server.Response) !void {
try response.headers.append("connection", "keep-alive");
}
+ // First try to read the file into the read buffer; also handle and return
+ // certain easy error codes here
const size = readFiles(response.request.target, &read) catch |err| {
switch (err) {
+ // Return an error 403 if the file is denied because of permissions
error.AccessDenied => {
response.status = .forbidden;
},
+ // Return an error 404 if the file is not found
error.FileNotFound => {
response.status = .not_found;
},
+ // Return an error 414 if the URI is too long to be read
error.OutOfMemory => {
response.status = .uri_too_long;
},
+ // Otherwise, some other error happened that I don't know. This
+ // will eventually return an error 500
else => {
return err;
},
}
+ // For all of the above error cases, it's not actually returning any
+ // data, so .content_length is 0
response.transfer_encoding = .{ .content_length = 0 };
try response.do();
return;
};
if (size >= buffer_limit) {
+ // If the amount read into read is as big as the buffer_limit, that
+ // means there was more text than could be processed and so this will
+ // return an error 413
response.status = .payload_too_large;
response.transfer_encoding = .{ .content_length = 0 };
try response.do();
@@ -130,12 +155,13 @@ fn handleRequest(response: *std.http.Server.Response) !void {
} else if (size > 0) {
// Get the file extension, and set the content-type header if it exists
// (using mime.zig)
- // To do this, we iterate through response.request.target in reverse
+ // To do this, iterate through response.request.target in reverse
// looking for a '/' or a '.'
// a '/' indicates a directory, so there is no extension
// a '.' indicates a file extension
var i: usize = response.request.target.len;
var mime_type: ?mime.Type = undefined;
+ // TODO properly handle files with no extension
if (std.mem.endsWith(u8, response.request.target, "/")) {
log.warn("Dir requested, returning index.html!", .{});
try response.headers.append("content-type", "text/html");
@@ -168,6 +194,7 @@ fn handleRequest(response: *std.http.Server.Response) !void {
if (mime_type) |mime_val| {
try response.headers.append("content-type", @tagName(mime_val));
} else {
+ // Should maybe return error 415?
try response.headers.append("content-type", "text/plain");
}
}