Created
May 8, 2023 13:53
-
-
Save zigster64/ceb434851930a41cb0b6663eb8c6c4f4 to your computer and use it in GitHub Desktop.
simple threadpool webserver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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