mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 22:16:08 +00:00
Fix middleware render detection
This commit is contained in:
parent
1565ae3b73
commit
9684181c64
@ -11,6 +11,16 @@ pub const Method = enum { DELETE, GET, PATCH, POST, HEAD, PUT, CONNECT, OPTIONS,
|
||||
pub const Modifier = enum { edit, new };
|
||||
pub const Format = enum { HTML, JSON, UNKNOWN };
|
||||
pub const Protocol = enum { http, https };
|
||||
pub const RequestState = enum {
|
||||
initial, // No processing has taken place
|
||||
processed, // Request headers have been processed
|
||||
after_request, // Initial middleware processing
|
||||
rendered, // Rendered by middleware or view
|
||||
redirected, // Redirected by middleware or view
|
||||
failed, // Failed by middleware or view
|
||||
before_response, // Post middleware processing
|
||||
finalized, // Response generated
|
||||
};
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
path: jetzig.http.Path,
|
||||
@ -30,14 +40,12 @@ parsed_multipart: ?*jetzig.data.Data = null,
|
||||
_cookies: ?*jetzig.http.Cookies = null,
|
||||
_session: ?*jetzig.http.Session = null,
|
||||
body: []const u8 = undefined,
|
||||
state: enum { initial, rendered, redirected, failed, processed } = .initial,
|
||||
response_started: bool = false,
|
||||
state: RequestState = .initial,
|
||||
dynamic_assigned_template: ?[]const u8 = null,
|
||||
layout: ?[]const u8 = null,
|
||||
layout_disabled: bool = false,
|
||||
redirect_state: ?RedirectState = null,
|
||||
middleware_rendered: ?struct { name: []const u8, action: []const u8 } = null,
|
||||
middleware_rendered_during_response: bool = false,
|
||||
middleware_data: jetzig.http.middleware.MiddlewareData = undefined,
|
||||
rendered_multiple: bool = false,
|
||||
rendered_view: ?jetzig.views.View = null,
|
||||
@ -172,6 +180,7 @@ pub fn respond(self: *Request) !void {
|
||||
const status = jetzig.http.status_codes.get(self.response.status_code);
|
||||
self.httpz_response.status = try status.getCodeInt();
|
||||
self.httpz_response.body = self.response.content;
|
||||
self.state = .finalized;
|
||||
}
|
||||
|
||||
/// Set the root value for response data.
|
||||
@ -186,10 +195,9 @@ pub fn data(self: Request, comptime root: @TypeOf(.enum_literal)) !*jetzig.Data.
|
||||
/// Render a response. This function can only be called once per request (repeat calls will
|
||||
/// trigger an error).
|
||||
pub fn render(self: *Request, status_code: jetzig.http.status_codes.StatusCode) jetzig.views.View {
|
||||
if (self.state != .processed) self.rendered_multiple = true;
|
||||
if (self.isRendered()) self.rendered_multiple = true;
|
||||
|
||||
self.state = .rendered;
|
||||
if (self.response_started) self.middleware_rendered_during_response = true;
|
||||
self.rendered_view = .{ .data = self.response_data, .status_code = status_code };
|
||||
return self.rendered_view.?;
|
||||
}
|
||||
@ -197,14 +205,20 @@ pub fn render(self: *Request, status_code: jetzig.http.status_codes.StatusCode)
|
||||
/// Render an error. This function can only be called once per request (repeat calls will
|
||||
/// trigger an error).
|
||||
pub fn fail(self: *Request, status_code: jetzig.http.status_codes.StatusCode) jetzig.views.View {
|
||||
if (self.state != .processed) self.rendered_multiple = true;
|
||||
if (self.isRendered()) self.rendered_multiple = true;
|
||||
|
||||
self.state = .failed;
|
||||
if (self.response_started) self.middleware_rendered_during_response = true;
|
||||
self.rendered_view = .{ .data = self.response_data, .status_code = status_code };
|
||||
return self.rendered_view.?;
|
||||
}
|
||||
|
||||
pub inline fn isRendered(self: *const Request) bool {
|
||||
return switch (self.state) {
|
||||
.initial, .processed, .after_request, .before_response => false,
|
||||
.rendered, .redirected, .failed, .finalized => true,
|
||||
};
|
||||
}
|
||||
|
||||
/// Issue a redirect to a new location.
|
||||
/// ```zig
|
||||
/// return request.redirect("https://www.example.com/", .moved_permanently);
|
||||
@ -218,10 +232,9 @@ pub fn redirect(
|
||||
location: []const u8,
|
||||
redirect_status: enum { moved_permanently, found },
|
||||
) jetzig.views.View {
|
||||
if (self.state != .processed) self.rendered_multiple = true;
|
||||
if (self.isRendered()) self.rendered_multiple = true;
|
||||
|
||||
self.state = .redirected;
|
||||
if (self.response_started) self.middleware_rendered_during_response = true;
|
||||
|
||||
const status_code = switch (redirect_status) {
|
||||
.moved_permanently => jetzig.http.status_codes.StatusCode.moved_permanently,
|
||||
|
@ -138,7 +138,8 @@ pub fn processNextRequest(
|
||||
|
||||
var middleware_data = try jetzig.http.middleware.afterRequest(&request);
|
||||
|
||||
if (request.middleware_rendered) |_| { // Request processing ends when a middleware renders or redirects.
|
||||
if (request.middleware_rendered) |_| {
|
||||
// Request processing ends when a middleware renders or redirects.
|
||||
if (request.redirect_state) |state| {
|
||||
try request.renderRedirect(state);
|
||||
} else if (request.rendered_view) |rendered| {
|
||||
@ -150,8 +151,8 @@ pub fn processNextRequest(
|
||||
} else {
|
||||
try self.renderResponse(&request);
|
||||
try request.response.headers.append("Content-Type", response.content_type);
|
||||
try jetzig.http.middleware.beforeResponse(&middleware_data, &request);
|
||||
|
||||
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);
|
||||
@ -371,7 +372,7 @@ fn renderView(
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (request.state != .redirected) {
|
||||
if (request.state == .processed) {
|
||||
try self.logger.WARN("`request.render` was not invoked. Rendering empty content.", .{});
|
||||
}
|
||||
request.response_data.reset();
|
||||
@ -475,8 +476,6 @@ fn renderInternalServerError(
|
||||
stack_trace: ?*std.builtin.StackTrace,
|
||||
err: anyerror,
|
||||
) !RenderedView {
|
||||
// request.response_data.reset();
|
||||
|
||||
try self.logger.logError(stack_trace, err);
|
||||
|
||||
const status = jetzig.http.StatusCode.internal_server_error;
|
||||
|
@ -60,8 +60,11 @@ pub fn afterRequest(request: *jetzig.http.Request) !MiddlewareData {
|
||||
}
|
||||
}
|
||||
|
||||
request.state = .after_request;
|
||||
|
||||
inline for (middlewares, 0..) |middleware, index| {
|
||||
if (comptime !@hasDecl(middleware, "afterRequest")) continue;
|
||||
|
||||
if (comptime @hasDecl(middleware, "init")) {
|
||||
const data = middleware_data.get(index).?;
|
||||
try @call(
|
||||
@ -72,7 +75,8 @@ pub fn afterRequest(request: *jetzig.http.Request) !MiddlewareData {
|
||||
} else {
|
||||
try @call(.always_inline, middleware.afterRequest, .{request});
|
||||
}
|
||||
if (request.state != .initial) {
|
||||
|
||||
if (request.state != .after_request) {
|
||||
request.middleware_rendered = .{ .name = @typeName(middleware), .action = "afterRequest" };
|
||||
break;
|
||||
}
|
||||
@ -86,11 +90,11 @@ pub fn beforeResponse(
|
||||
middleware_data: *MiddlewareData,
|
||||
request: *jetzig.http.Request,
|
||||
) !void {
|
||||
request.response_started = true;
|
||||
request.state = .before_response;
|
||||
|
||||
inline for (middlewares, 0..) |middleware, index| {
|
||||
if (comptime !@hasDecl(middleware, "beforeResponse")) continue;
|
||||
if (!request.middleware_rendered_during_response) {
|
||||
if (request.state == .before_response) {
|
||||
if (comptime @hasDecl(middleware, "init")) {
|
||||
const data = middleware_data.get(index).?;
|
||||
try @call(
|
||||
@ -99,10 +103,15 @@ pub fn beforeResponse(
|
||||
.{ @as(*middleware, @ptrCast(@alignCast(data))), request, request.response },
|
||||
);
|
||||
} else {
|
||||
try @call(.always_inline, middleware.beforeResponse, .{ request, request.response });
|
||||
try @call(
|
||||
.always_inline,
|
||||
middleware.beforeResponse,
|
||||
.{ request, request.response },
|
||||
);
|
||||
}
|
||||
}
|
||||
if (request.middleware_rendered_during_response) {
|
||||
|
||||
if (request.state != .before_response) {
|
||||
request.middleware_rendered = .{
|
||||
.name = @typeName(middleware),
|
||||
.action = "beforeResponse",
|
||||
|
@ -20,7 +20,11 @@ pub fn afterRequest(request: *jetzig.http.Request) !void {
|
||||
/// If a redirect was issued during request processing, reset any response data, set response
|
||||
/// status to `200 OK` and replace the `Location` header with a `HX-Redirect` header.
|
||||
pub fn beforeResponse(request: *jetzig.http.Request, response: *jetzig.http.Response) !void {
|
||||
if (response.status_code != .moved_permanently and response.status_code != .found) return;
|
||||
switch (response.status_code) {
|
||||
.moved_permanently, .found => {},
|
||||
else => return,
|
||||
}
|
||||
|
||||
if (request.headers.get("HX-Request") == null) return;
|
||||
|
||||
if (response.headers.get("Location")) |location| {
|
||||
|
Loading…
x
Reference in New Issue
Block a user