mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 05:56:07 +00:00
Implement request.renderTemplate
Clean up request state.
This commit is contained in:
parent
036aec1682
commit
8095bbcb76
15
demo/src/app/views/render_template.zig
Normal file
15
demo/src/app/views/render_template.zig
Normal file
@ -0,0 +1,15 @@
|
||||
const std = @import("std");
|
||||
const jetzig = @import("jetzig");
|
||||
|
||||
pub fn index(request: *jetzig.Request) !jetzig.View {
|
||||
return request.renderTemplate("basic/index", .ok);
|
||||
}
|
||||
|
||||
test "index" {
|
||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
||||
defer app.deinit();
|
||||
|
||||
const response = try app.request(.GET, "/render_template", .{});
|
||||
try response.expectStatus(.ok);
|
||||
try response.expectBodyContains("Hello");
|
||||
}
|
3
demo/src/app/views/render_template/index.zmpl
Normal file
3
demo/src/app/views/render_template/index.zmpl
Normal file
@ -0,0 +1,3 @@
|
||||
<div>
|
||||
<span>Content goes here</span>
|
||||
</div>
|
@ -30,16 +30,11 @@ parsed_multipart: ?*jetzig.data.Data = null,
|
||||
_cookies: ?*jetzig.http.Cookies = null,
|
||||
_session: ?*jetzig.http.Session = null,
|
||||
body: []const u8 = undefined,
|
||||
state: enum { initial, processed } = .initial,
|
||||
state: enum { initial, rendered, redirected, failed, processed } = .initial,
|
||||
response_started: bool = false,
|
||||
dynamic_assigned_template: ?[]const u8 = null,
|
||||
layout: ?[]const u8 = null,
|
||||
layout_disabled: bool = false,
|
||||
// TODO: Squash rendered/redirected/failed into
|
||||
// `state: enum { initial, rendered, redirected, failed }`
|
||||
rendered: bool = false,
|
||||
redirected: bool = false,
|
||||
failed: bool = false,
|
||||
redirect_state: ?RedirectState = null,
|
||||
middleware_rendered: ?struct { name: []const u8, action: []const u8 } = null,
|
||||
middleware_rendered_during_response: bool = false,
|
||||
@ -191,9 +186,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.rendered or self.failed) self.rendered_multiple = true;
|
||||
if (self.state != .processed) self.rendered_multiple = true;
|
||||
|
||||
self.rendered = 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.?;
|
||||
@ -202,10 +197,9 @@ 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.rendered or self.redirected) self.rendered_multiple = true;
|
||||
if (self.state != .processed) self.rendered_multiple = true;
|
||||
|
||||
self.rendered = true;
|
||||
self.failed = 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.?;
|
||||
@ -224,10 +218,9 @@ pub fn redirect(
|
||||
location: []const u8,
|
||||
redirect_status: enum { moved_permanently, found },
|
||||
) jetzig.views.View {
|
||||
if (self.rendered or self.failed) self.rendered_multiple = true;
|
||||
if (self.state != .processed) self.rendered_multiple = true;
|
||||
|
||||
self.rendered = true;
|
||||
self.redirected = true;
|
||||
self.state = .redirected;
|
||||
if (self.response_started) self.middleware_rendered_during_response = true;
|
||||
|
||||
const status_code = switch (redirect_status) {
|
||||
@ -687,6 +680,19 @@ pub fn setTemplate(self: *Request, name: []const u8) void {
|
||||
self.dynamic_assigned_template = name;
|
||||
}
|
||||
|
||||
/// Set a custom template and render the response.
|
||||
/// ```zig
|
||||
/// return request.renderTemplate("blogs/comments/get", .ok);
|
||||
/// ```
|
||||
pub fn renderTemplate(
|
||||
self: *Request,
|
||||
name: []const u8,
|
||||
status_code: jetzig.http.StatusCode,
|
||||
) jetzig.views.View {
|
||||
self.dynamic_assigned_template = name;
|
||||
return self.render(status_code);
|
||||
}
|
||||
|
||||
pub fn joinPath(self: *const Request, args: anytype) ![]const u8 {
|
||||
const fields = std.meta.fields(@TypeOf(args));
|
||||
var buf: [fields.len][]const u8 = undefined;
|
||||
|
@ -197,9 +197,9 @@ fn renderResponse(self: *Server, request: *jetzig.http.Request) !void {
|
||||
for (route.before_callbacks) |callback| {
|
||||
try callback(request, route);
|
||||
if (request.rendered_view) |view| {
|
||||
if (request.failed) {
|
||||
if (request.state == .failed) {
|
||||
request.setResponse(try self.renderError(request, view.status_code), .{});
|
||||
} else if (request.rendered) {
|
||||
} else if (request.state == .rendered) {
|
||||
// TODO: Allow callbacks to set content
|
||||
}
|
||||
return;
|
||||
@ -259,7 +259,9 @@ fn renderHTML(
|
||||
return request.setResponse(rendered_error, .{});
|
||||
};
|
||||
|
||||
return if (request.redirected or request.failed or request.dynamic_assigned_template != null)
|
||||
return if (request.state == .redirected or
|
||||
request.state == .failed or
|
||||
request.dynamic_assigned_template != null)
|
||||
request.setResponse(rendered, .{})
|
||||
else
|
||||
request.setResponse(try self.renderNotFound(request), .{});
|
||||
@ -327,7 +329,7 @@ fn renderView(
|
||||
return try self.renderInternalServerError(request, @errorReturnTrace(), err);
|
||||
};
|
||||
|
||||
if (request.failed) {
|
||||
if (request.state == .failed) {
|
||||
const view: jetzig.views.View = request.rendered_view orelse .{
|
||||
.data = request.response_data,
|
||||
.status_code = .internal_server_error,
|
||||
@ -343,7 +345,7 @@ fn renderView(
|
||||
if (request.rendered_multiple) return error.JetzigMultipleRenderError;
|
||||
|
||||
if (request.rendered_view) |rendered_view| {
|
||||
if (request.redirected) return .{ .view = rendered_view, .content = "" };
|
||||
if (request.state == .redirected) return .{ .view = rendered_view, .content = "" };
|
||||
|
||||
if (template) |capture| {
|
||||
return .{
|
||||
@ -351,13 +353,17 @@ fn renderView(
|
||||
.content = try self.renderTemplateWithLayout(request, capture, rendered_view, route),
|
||||
};
|
||||
} else {
|
||||
try self.logger.DEBUG(
|
||||
"Missing template for route `{s}.{s}`. Expected: `src/app/views/{s}.zmpl`.",
|
||||
.{ route.view_name, @tagName(route.action), route.template },
|
||||
);
|
||||
return switch (request.requestFormat()) {
|
||||
.HTML, .UNKNOWN => try self.renderNotFound(request),
|
||||
.JSON => .{ .view = rendered_view, .content = "" },
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (!request.redirected) {
|
||||
if (request.state != .redirected) {
|
||||
try self.logger.WARN("`request.render` was not invoked. Rendering empty content.", .{});
|
||||
}
|
||||
request.response_data.reset();
|
||||
|
@ -72,7 +72,7 @@ pub fn afterRequest(request: *jetzig.http.Request) !MiddlewareData {
|
||||
} else {
|
||||
try @call(.always_inline, middleware.afterRequest, .{request});
|
||||
}
|
||||
if (request.rendered or request.redirected) {
|
||||
if (request.state != .initial) {
|
||||
request.middleware_rendered = .{ .name = @typeName(middleware), .action = "afterRequest" };
|
||||
break;
|
||||
}
|
||||
@ -103,7 +103,10 @@ pub fn beforeResponse(
|
||||
}
|
||||
}
|
||||
if (request.middleware_rendered_during_response) {
|
||||
request.middleware_rendered = .{ .name = @typeName(middleware), .action = "beforeResponse" };
|
||||
request.middleware_rendered = .{
|
||||
.name = @typeName(middleware),
|
||||
.action = "beforeResponse",
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ pub fn logRequest(self: DevelopmentLogger, request: *const jetzig.http.Request)
|
||||
if (request.middleware_rendered) |middleware| middleware.action else "",
|
||||
if (request.middleware_rendered) |_| jetzig.colors.codes.escape ++ jetzig.colors.codes.white ++ ":" else "",
|
||||
if (request.middleware_rendered) |_| jetzig.colors.codes.escape ++ jetzig.colors.codes.bright_cyan else "",
|
||||
if (request.middleware_rendered) |_| if (request.redirected) "redirect" else "render" else "",
|
||||
if (request.middleware_rendered) |_| @tagName(request.state) else "",
|
||||
if (request.middleware_rendered) |_| jetzig.colors.codes.escape ++ jetzig.colors.codes.reset else "",
|
||||
if (request.middleware_rendered) |_| "]" else "",
|
||||
request.path.path,
|
||||
|
@ -86,7 +86,7 @@ pub fn logRequest(self: ProductionLogger, request: *const jetzig.http.Request) !
|
||||
if (request.middleware_rendered) |_| ":" else "",
|
||||
if (request.middleware_rendered) |middleware| middleware.action else "",
|
||||
if (request.middleware_rendered) |_| ":" else "",
|
||||
if (request.middleware_rendered) |_| if (request.redirected) "redirect" else "render" else "",
|
||||
if (request.middleware_rendered) |_| @tagName(request.state) else "",
|
||||
if (request.middleware_rendered) |_| "]" else "",
|
||||
request.path.path,
|
||||
}, .stdout);
|
||||
|
Loading…
x
Reference in New Issue
Block a user