Skip to content

Instantly share code, notes, and snippets.

@zigster64
Created May 8, 2023 13:53
Show Gist options
  • Save zigster64/ceb434851930a41cb0b6663eb8c6c4f4 to your computer and use it in GitHub Desktop.
Save zigster64/ceb434851930a41cb0b6663eb8c6c4f4 to your computer and use it in GitHub Desktop.
simple threadpool webserver
const std = @import("std");
const Self = @This();
fn runLoop(self: *Self) !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var server = std.http.Server.init(allocator, .{ .reuse_address = true, .kernel_backlog = 4096 });
defer server.deinit();
var listen_address = try std.net.Address.resolveIp("127.0.0.1", self.config.port);
try server.listen(listen_address);
var thread_id: usize = 0;
var pool: std.Thread.Pool = undefined;
try std.Thread.Pool.init(&pool, .{ .allocator = allocator, .n_jobs = 4 });
while (true) {
thread_id += 1;
const res = try server.accept(.{ .allocator = allocator });
// clone the stack based response to the heap so it can be owned by the thread, and freed up there where the thread is done
var response_clone_owned = try allocator.create(std.http.Server.Response);
response_clone_owned.* = res;
try std.Thread.Pool.spawn(&pool, handler, .{ self, thread_id, response_clone_owned });
}
}
fn handler(self: *Self, thread_id: usize, response: *std.http.Server.Response) void {
while (true) {
response.wait() catch break;
response.headers.append("server", "Muh-Server") catch return;
switch (response.request.method) {
.GET => {
self.handleGet(response) catch return;
},
.POST => {
self.handlePost(thread_id, response) catch return;
},
else => {
response.status = .bad_request;
response.do() catch return;
},
}
response.finish() catch return;
if (response.reset() == .closing) {
break;
}
}
}
fn handleGet(self: Self, res: *std.http.Server.Response) !void {
// Do the GET request
//
// for a file server it would be something like :
// - read the file
// - set the res.transfer_encoding = .{ .content_length = size of output }
// - set the mime type
// - res.do()
// - res.write (conntents of the file)
// - res.finish()
}
fn handlePost(self: *Self, thread_id: usize, res: *std.http.Server.Response) !void {
// Do the POST request
// example
// - read the res.request.body input payload
// - decode and parse the input payload
// - calculate the response payload
// - set the res headers
// - res.do()
// - res.write() the response payload
// - res.finish()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment