This commit is contained in:
Bob Farrell 2024-05-07 21:26:25 +01:00
parent 6e4048a318
commit 1693f24ce2
4 changed files with 73 additions and 71 deletions

View File

@ -3,7 +3,7 @@ const builtin = @import("builtin");
pub const Server = @import("http/Server.zig");
pub const Request = if (builtin.os.tag == .windows)
@import("http/RequestWindows.zig")
@import("windows/Request.zig")
else
@import("http/Request.zig");
pub const StaticRequest = @import("http/StaticRequest.zig");

View File

@ -72,7 +72,7 @@ const Dispatcher = struct {
};
pub fn listen(self: *Server) !void {
if (builtin.os.tag == .windows) return try self.listenWindows();
if (builtin.os.tag == .windows) return try @import("../windows.zig").listen(self);
var httpz_server = try httpz.ServerCtx(Dispatcher, Dispatcher).init(
self.allocator,
@ -103,73 +103,6 @@ pub fn errorHandlerFn(self: *Server, request: *httpz.Request, response: *httpz.R
response.body = "500 Internal Server Error";
}
// TODO: http.zig windows
pub fn listenWindows(self: *Server) !void {
const address = try std.net.Address.parseIp(self.options.bind, self.options.port);
self.std_net_server = try address.listen(.{ .reuse_port = true });
self.initialized = true;
try self.logger.INFO("Listening on http://{s}:{} [{s}]", .{
self.options.bind,
self.options.port,
@tagName(self.options.environment),
});
try self.processRequestsWindows();
}
// TODO: http.zig windows
fn processRequestsWindows(self: *Server) !void {
while (true) {
var arena = std.heap.ArenaAllocator.init(self.allocator);
errdefer arena.deinit();
const allocator = arena.allocator();
const connection = try self.std_net_server.accept();
var buf: [jetzig.config.get(usize, "http_buffer_size")]u8 = undefined;
var std_http_server = std.http.Server.init(connection, &buf);
errdefer std_http_server.connection.stream.close();
self.processNextRequestWindows(allocator, &std_http_server) catch |err| {
if (isBadHttpError(err)) {
std_http_server.connection.stream.close();
continue;
} else return err;
};
std_http_server.connection.stream.close();
arena.deinit();
}
}
// TODO: http.zig windows
fn processNextRequestWindows(self: *Server, allocator: std.mem.Allocator, std_http_server: *std.http.Server) !void {
const start_time = std.time.nanoTimestamp();
const std_http_request = try std_http_server.receiveHead();
if (std_http_server.state == .receiving_head) return error.JetzigParseHeadError;
var response = try jetzig.http.Response.init(allocator);
var request = try jetzig.http.Request.init(allocator, self, start_time, std_http_request, &response);
try request.process();
var middleware_data = try jetzig.http.middleware.afterRequest(&request);
try self.renderResponse(&request);
try request.response.headers.append("content-type", response.content_type);
try jetzig.http.middleware.beforeResponse(&middleware_data, &request);
try request.respond();
try jetzig.http.middleware.afterResponse(&middleware_data, &request);
jetzig.http.middleware.deinit(&middleware_data, &request);
try self.logger.logRequest(&request);
}
fn processNextRequest(
self: *Server,
httpz_request: *httpz.Request,
@ -217,7 +150,8 @@ fn processNextRequest(
try self.logger.logRequest(&request);
}
fn renderResponse(self: *Server, request: *jetzig.http.Request) !void {
// TODO: Make private when http.zig Windows is working
pub fn renderResponse(self: *Server, request: *jetzig.http.Request) !void {
const static_resource = self.matchStaticResource(request) catch |err| {
if (isUnhandledError(err)) return err;
@ -398,7 +332,8 @@ fn isUnhandledError(err: anyerror) bool {
};
}
fn isBadHttpError(err: anyerror) bool {
// TODO: Make private when http.zig Windows is working
pub fn isBadHttpError(err: anyerror) bool {
return switch (err) {
error.JetzigParseHeadError,
error.UnknownHttpMethod,

67
src/jetzig/windows.zig Normal file
View File

@ -0,0 +1,67 @@
const std = @import("std");
const Server = @import("http/Server.zig");
const jetzig = @import("../jetzig.zig");
pub fn listen(self: *Server) !void {
const address = try std.net.Address.parseIp(self.options.bind, self.options.port);
self.std_net_server = try address.listen(.{ .reuse_port = true });
self.initialized = true;
try self.logger.INFO("Listening on http://{s}:{} [{s}]", .{
self.options.bind,
self.options.port,
@tagName(self.options.environment),
});
try processRequests(self);
}
fn processRequests(self: *Server) !void {
while (true) {
var arena = std.heap.ArenaAllocator.init(self.allocator);
errdefer arena.deinit();
const allocator = arena.allocator();
const connection = try self.std_net_server.accept();
var buf: [jetzig.config.get(usize, "http_buffer_size")]u8 = undefined;
var std_http_server = std.http.Server.init(connection, &buf);
errdefer std_http_server.connection.stream.close();
processNextRequest(self, allocator, &std_http_server) catch |err| {
if (Server.isBadHttpError(err)) {
std_http_server.connection.stream.close();
continue;
} else return err;
};
std_http_server.connection.stream.close();
arena.deinit();
}
}
fn processNextRequest(self: *Server, allocator: std.mem.Allocator, std_http_server: *std.http.Server) !void {
const start_time = std.time.nanoTimestamp();
const std_http_request = try std_http_server.receiveHead();
if (std_http_server.state == .receiving_head) return error.JetzigParseHeadError;
var response = try jetzig.http.Response.init(allocator);
var request = try jetzig.http.Request.init(allocator, self, start_time, std_http_request, &response);
try request.process();
var middleware_data = try jetzig.http.middleware.afterRequest(&request);
try self.renderResponse(&request);
try request.response.headers.append("content-type", response.content_type);
try jetzig.http.middleware.beforeResponse(&middleware_data, &request);
try request.respond();
try jetzig.http.middleware.afterResponse(&middleware_data, &request);
jetzig.http.middleware.deinit(&middleware_data, &request);
try self.logger.logRequest(&request);
}