diff --git a/src/jetzig/http.zig b/src/jetzig/http.zig index f558717..4786f20 100644 --- a/src/jetzig/http.zig +++ b/src/jetzig/http.zig @@ -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"); diff --git a/src/jetzig/http/Server.zig b/src/jetzig/http/Server.zig index 242d975..b8a237f 100644 --- a/src/jetzig/http/Server.zig +++ b/src/jetzig/http/Server.zig @@ -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, diff --git a/src/jetzig/windows.zig b/src/jetzig/windows.zig new file mode 100644 index 0000000..37085d3 --- /dev/null +++ b/src/jetzig/windows.zig @@ -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); +} diff --git a/src/jetzig/http/RequestWindows.zig b/src/jetzig/windows/Request.zig similarity index 100% rename from src/jetzig/http/RequestWindows.zig rename to src/jetzig/windows/Request.zig