Middleware created

This commit is contained in:
rimuspp 2024-02-07 12:54:54 +00:00
parent 5623be3e65
commit 267bf44017
3 changed files with 84 additions and 4 deletions

View File

@ -3,6 +3,6 @@
// This file should _not_ be stored in version control.
pub const templates = struct {
pub const index = @import(".index.zmpl.compiled.zig");
pub const quotes_get = @import("quotes/.get.zmpl.compiled.zig");
pub const users_get = @import("users/.get.zmpl.compiled.zig");
pub const quotes_get = @import("quotes/.get.zmpl.compiled.zig");
};

View File

@ -2,6 +2,10 @@ const std = @import("std");
const jetzig = @import("../../jetzig.zig");
const root_file = @import("root");
const jetzig_server_options = if (@hasDecl(root_file, "jetzig_options")) root_file.jetzig_options else struct {};
const middlewares: []const type = jetzig_server_options.middleware;
pub const ServerOptions = struct {
cache: jetzig.caches.Cache,
logger: jetzig.loggers.Logger,
@ -30,7 +34,7 @@ pub fn init(
routes: []jetzig.views.Route,
templates: []jetzig.TemplateFn,
) Self {
const server = std.http.Server.init( .{ .reuse_address = true });
const server = std.http.Server.init(.{ .reuse_address = true });
return .{
.server = server,
@ -93,9 +97,36 @@ fn processNextRequest(self: *Self, response: *std.http.Server.Response) !void {
var request = try jetzig.http.Request.init(arena.allocator(), self, response);
defer request.deinit();
const result = try self.pageContent(&request);
var middleware_data = std.BoundedArray(*anyopaque, middlewares.len).init(0) catch unreachable;
inline for (middlewares, 0..) |middleware, i| {
if (comptime !@hasDecl(middleware, "init")) continue;
const data = try @call(.always_inline, middleware.init, .{&request});
middleware_data.insert(i, data) catch unreachable; // We cannot overflow here because we know the length of the array
}
inline for (middlewares, 0..) |middleware, i| {
if (comptime !@hasDecl(middleware, "beforeRequest")) continue;
if (comptime @hasDecl(middleware, "init")) {
const data = middleware_data.get(i);
try @call(.always_inline, middleware.beforeRequest, .{ @as(*middleware, @ptrCast(@alignCast(data))), &request });
} else {
try @call(.always_inline, middleware.beforeRequest, .{&request});
}
}
var result = try self.pageContent(&request);
defer result.deinit();
inline for (middlewares, 0..) |middleware, i| {
if (comptime !@hasDecl(middleware, "afterRequest")) continue;
if (comptime @hasDecl(middleware, "init")) {
const data = middleware_data.get(i);
try @call(.always_inline, middleware.afterRequest, .{ @as(*middleware, @ptrCast(@alignCast(data))), &request, &result });
} else {
try @call(.always_inline, middleware.afterRequest, .{ &request, &result });
}
}
response.transfer_encoding = .{ .content_length = result.value.content.len };
var cookie_it = request.cookies.headerIterator();
while (try cookie_it.next()) |header| {
@ -114,6 +145,15 @@ fn processNextRequest(self: *Self, response: *std.http.Server.Response) !void {
const log_message = try self.requestLogMessage(&request, result);
defer self.allocator.free(log_message);
self.logger.debug("{s}", .{log_message});
inline for (middlewares, 0..) |middleware, i| {
if (comptime @hasDecl(middleware, "init")) {
if (comptime @hasDecl(middleware, "deinit")) {
const data = middleware_data.get(i);
@call(.always_inline, middleware.deinit, .{ @as(*middleware, @ptrCast(@alignCast(data))), &request });
}
}
}
}
fn pageContent(self: *Self, request: *jetzig.http.Request) !jetzig.caches.Result {
@ -307,7 +347,7 @@ fn matchStaticResource(self: *Self, request: *jetzig.http.Request) !?StaticResou
if (request.path.len < 2) return null;
if (request.method != .GET) return null;
var iterable_dir = std.fs.cwd().openDir("public", .{.iterate = true}) catch |err| {
var iterable_dir = std.fs.cwd().openDir("public", .{ .iterate = true }) catch |err| {
switch (err) {
error.FileNotFound => return null,
else => return err,

View File

@ -4,6 +4,10 @@ pub const jetzig = @import("jetzig");
pub const templates = @import("app/views/zmpl.manifest.zig").templates;
pub const routes = @import("app/views/routes.zig").routes;
pub const jetzig_options = struct {
pub const middleware: []const type = &.{ TestMiddleware, IncompleteMiddleware, IncompleteMiddleware2 };
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(gpa.deinit() == .ok);
@ -17,3 +21,39 @@ pub fn main() !void {
comptime jetzig.loadTemplates(templates),
);
}
const TestMiddleware = struct {
my_data: u8,
pub fn init(request: *jetzig.http.Request) !*TestMiddleware {
var mw = try request.allocator.create(TestMiddleware);
mw.my_data = 42;
return mw;
}
pub fn beforeRequest(middleware: *TestMiddleware, request: *jetzig.http.Request) !void {
request.server.logger.debug("Before request, custom data: {d}", .{middleware.my_data});
middleware.my_data = 43;
}
pub fn afterRequest(middleware: *TestMiddleware, request: *jetzig.http.Request, result: *jetzig.caches.Result) !void {
request.server.logger.debug("After request, custom data: {d}", .{middleware.my_data});
request.server.logger.debug("{s}", .{result.value.content});
}
pub fn deinit(middleware: *TestMiddleware, request: *jetzig.http.Request) void {
request.allocator.destroy(middleware);
}
};
const IncompleteMiddleware = struct {
pub fn beforeRequest(request: *jetzig.http.Request) !void {
request.server.logger.debug("Before request", .{});
}
};
const IncompleteMiddleware2 = struct {
pub fn afterRequest(request: *jetzig.http.Request, result: *jetzig.caches.Result) !void {
request.server.logger.debug("After request", .{});
_ = result;
}
};