mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 14:06:08 +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,
|
_cookies: ?*jetzig.http.Cookies = null,
|
||||||
_session: ?*jetzig.http.Session = null,
|
_session: ?*jetzig.http.Session = null,
|
||||||
body: []const u8 = undefined,
|
body: []const u8 = undefined,
|
||||||
state: enum { initial, processed } = .initial,
|
state: enum { initial, rendered, redirected, failed, processed } = .initial,
|
||||||
response_started: bool = false,
|
response_started: bool = false,
|
||||||
dynamic_assigned_template: ?[]const u8 = null,
|
dynamic_assigned_template: ?[]const u8 = null,
|
||||||
layout: ?[]const u8 = null,
|
layout: ?[]const u8 = null,
|
||||||
layout_disabled: bool = false,
|
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,
|
redirect_state: ?RedirectState = null,
|
||||||
middleware_rendered: ?struct { name: []const u8, action: []const u8 } = null,
|
middleware_rendered: ?struct { name: []const u8, action: []const u8 } = null,
|
||||||
middleware_rendered_during_response: bool = false,
|
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
|
/// Render a response. This function can only be called once per request (repeat calls will
|
||||||
/// trigger an error).
|
/// trigger an error).
|
||||||
pub fn render(self: *Request, status_code: jetzig.http.status_codes.StatusCode) jetzig.views.View {
|
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;
|
if (self.response_started) self.middleware_rendered_during_response = true;
|
||||||
self.rendered_view = .{ .data = self.response_data, .status_code = status_code };
|
self.rendered_view = .{ .data = self.response_data, .status_code = status_code };
|
||||||
return self.rendered_view.?;
|
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
|
/// Render an error. This function can only be called once per request (repeat calls will
|
||||||
/// trigger an error).
|
/// trigger an error).
|
||||||
pub fn fail(self: *Request, status_code: jetzig.http.status_codes.StatusCode) jetzig.views.View {
|
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.state = .failed;
|
||||||
self.failed = true;
|
|
||||||
if (self.response_started) self.middleware_rendered_during_response = true;
|
if (self.response_started) self.middleware_rendered_during_response = true;
|
||||||
self.rendered_view = .{ .data = self.response_data, .status_code = status_code };
|
self.rendered_view = .{ .data = self.response_data, .status_code = status_code };
|
||||||
return self.rendered_view.?;
|
return self.rendered_view.?;
|
||||||
@ -224,10 +218,9 @@ pub fn redirect(
|
|||||||
location: []const u8,
|
location: []const u8,
|
||||||
redirect_status: enum { moved_permanently, found },
|
redirect_status: enum { moved_permanently, found },
|
||||||
) jetzig.views.View {
|
) 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 = .redirected;
|
||||||
self.redirected = true;
|
|
||||||
if (self.response_started) self.middleware_rendered_during_response = true;
|
if (self.response_started) self.middleware_rendered_during_response = true;
|
||||||
|
|
||||||
const status_code = switch (redirect_status) {
|
const status_code = switch (redirect_status) {
|
||||||
@ -687,6 +680,19 @@ pub fn setTemplate(self: *Request, name: []const u8) void {
|
|||||||
self.dynamic_assigned_template = name;
|
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 {
|
pub fn joinPath(self: *const Request, args: anytype) ![]const u8 {
|
||||||
const fields = std.meta.fields(@TypeOf(args));
|
const fields = std.meta.fields(@TypeOf(args));
|
||||||
var buf: [fields.len][]const u8 = undefined;
|
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| {
|
for (route.before_callbacks) |callback| {
|
||||||
try callback(request, route);
|
try callback(request, route);
|
||||||
if (request.rendered_view) |view| {
|
if (request.rendered_view) |view| {
|
||||||
if (request.failed) {
|
if (request.state == .failed) {
|
||||||
request.setResponse(try self.renderError(request, view.status_code), .{});
|
request.setResponse(try self.renderError(request, view.status_code), .{});
|
||||||
} else if (request.rendered) {
|
} else if (request.state == .rendered) {
|
||||||
// TODO: Allow callbacks to set content
|
// TODO: Allow callbacks to set content
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -259,7 +259,9 @@ fn renderHTML(
|
|||||||
return request.setResponse(rendered_error, .{});
|
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, .{})
|
request.setResponse(rendered, .{})
|
||||||
else
|
else
|
||||||
request.setResponse(try self.renderNotFound(request), .{});
|
request.setResponse(try self.renderNotFound(request), .{});
|
||||||
@ -327,7 +329,7 @@ fn renderView(
|
|||||||
return try self.renderInternalServerError(request, @errorReturnTrace(), err);
|
return try self.renderInternalServerError(request, @errorReturnTrace(), err);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (request.failed) {
|
if (request.state == .failed) {
|
||||||
const view: jetzig.views.View = request.rendered_view orelse .{
|
const view: jetzig.views.View = request.rendered_view orelse .{
|
||||||
.data = request.response_data,
|
.data = request.response_data,
|
||||||
.status_code = .internal_server_error,
|
.status_code = .internal_server_error,
|
||||||
@ -343,7 +345,7 @@ fn renderView(
|
|||||||
if (request.rendered_multiple) return error.JetzigMultipleRenderError;
|
if (request.rendered_multiple) return error.JetzigMultipleRenderError;
|
||||||
|
|
||||||
if (request.rendered_view) |rendered_view| {
|
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| {
|
if (template) |capture| {
|
||||||
return .{
|
return .{
|
||||||
@ -351,13 +353,17 @@ fn renderView(
|
|||||||
.content = try self.renderTemplateWithLayout(request, capture, rendered_view, route),
|
.content = try self.renderTemplateWithLayout(request, capture, rendered_view, route),
|
||||||
};
|
};
|
||||||
} else {
|
} 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()) {
|
return switch (request.requestFormat()) {
|
||||||
.HTML, .UNKNOWN => try self.renderNotFound(request),
|
.HTML, .UNKNOWN => try self.renderNotFound(request),
|
||||||
.JSON => .{ .view = rendered_view, .content = "" },
|
.JSON => .{ .view = rendered_view, .content = "" },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!request.redirected) {
|
if (request.state != .redirected) {
|
||||||
try self.logger.WARN("`request.render` was not invoked. Rendering empty content.", .{});
|
try self.logger.WARN("`request.render` was not invoked. Rendering empty content.", .{});
|
||||||
}
|
}
|
||||||
request.response_data.reset();
|
request.response_data.reset();
|
||||||
|
@ -72,7 +72,7 @@ pub fn afterRequest(request: *jetzig.http.Request) !MiddlewareData {
|
|||||||
} else {
|
} else {
|
||||||
try @call(.always_inline, middleware.afterRequest, .{request});
|
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" };
|
request.middleware_rendered = .{ .name = @typeName(middleware), .action = "afterRequest" };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -103,7 +103,10 @@ pub fn beforeResponse(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (request.middleware_rendered_during_response) {
|
if (request.middleware_rendered_during_response) {
|
||||||
request.middleware_rendered = .{ .name = @typeName(middleware), .action = "beforeResponse" };
|
request.middleware_rendered = .{
|
||||||
|
.name = @typeName(middleware),
|
||||||
|
.action = "beforeResponse",
|
||||||
|
};
|
||||||
break;
|
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) |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.white ++ ":" else "",
|
||||||
if (request.middleware_rendered) |_| jetzig.colors.codes.escape ++ jetzig.colors.codes.bright_cyan 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) |_| jetzig.colors.codes.escape ++ jetzig.colors.codes.reset else "",
|
||||||
if (request.middleware_rendered) |_| "]" else "",
|
if (request.middleware_rendered) |_| "]" else "",
|
||||||
request.path.path,
|
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) |_| ":" else "",
|
||||||
if (request.middleware_rendered) |middleware| middleware.action else "",
|
if (request.middleware_rendered) |middleware| middleware.action else "",
|
||||||
if (request.middleware_rendered) |_| ":" 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 "",
|
if (request.middleware_rendered) |_| "]" else "",
|
||||||
request.path.path,
|
request.path.path,
|
||||||
}, .stdout);
|
}, .stdout);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user