mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 22:16:08 +00:00
Merge pull request #54 from jetzig-framework/empty-http-params
Closes #53: Add support for empty HTTP query param
This commit is contained in:
commit
8096962cf6
@ -5,7 +5,15 @@ pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|||||||
_ = data;
|
_ = data;
|
||||||
const params = try request.params();
|
const params = try request.params();
|
||||||
if (params.get("redirect")) |location| {
|
if (params.get("redirect")) |location| {
|
||||||
return request.redirect(try location.toString(), .moved_permanently);
|
switch (location.*) {
|
||||||
|
// Value is `.Null` when param is empty, e.g.:
|
||||||
|
// `http://localhost:8080/redirect?redirect`
|
||||||
|
.Null => return request.redirect("http://www.example.com/", .moved_permanently),
|
||||||
|
// Value is `.string` when param is present, e.g.:
|
||||||
|
// `http://localhost:8080/redirect?redirect=https://jetzig.dev/`
|
||||||
|
.string => |string| return request.redirect(string.value, .moved_permanently),
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const jetzig = @import("../../jetzig.zig");
|
const jetzig = @import("../../jetzig.zig");
|
||||||
|
|
||||||
const Self = @This();
|
const Query = @This();
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
query_string: []const u8,
|
query_string: []const u8,
|
||||||
@ -10,10 +10,10 @@ data: *jetzig.data.Data,
|
|||||||
|
|
||||||
pub const QueryItem = struct {
|
pub const QueryItem = struct {
|
||||||
key: []const u8,
|
key: []const u8,
|
||||||
value: []const u8,
|
value: ?[]const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, query_string: []const u8, data: *jetzig.data.Data) Self {
|
pub fn init(allocator: std.mem.Allocator, query_string: []const u8, data: *jetzig.data.Data) Query {
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.query_string = query_string,
|
.query_string = query_string,
|
||||||
@ -22,19 +22,19 @@ pub fn init(allocator: std.mem.Allocator, query_string: []const u8, data: *jetzi
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Query) void {
|
||||||
self.query_items.deinit();
|
self.query_items.deinit();
|
||||||
self.data.deinit();
|
self.data.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(self: *Self) !void {
|
pub fn parse(self: *Query) !void {
|
||||||
var pairs_it = std.mem.splitScalar(u8, self.query_string, '&');
|
var pairs_it = std.mem.splitScalar(u8, self.query_string, '&');
|
||||||
|
|
||||||
while (pairs_it.next()) |pair| {
|
while (pairs_it.next()) |pair| {
|
||||||
var key_value_it = std.mem.splitScalar(u8, pair, '=');
|
var key_value_it = std.mem.splitScalar(u8, pair, '=');
|
||||||
var count: u2 = 0;
|
var count: u2 = 0;
|
||||||
var key: []const u8 = undefined;
|
var key: []const u8 = undefined;
|
||||||
var value: []const u8 = undefined;
|
var value: ?[]const u8 = null;
|
||||||
|
|
||||||
while (key_value_it.next()) |key_or_value| {
|
while (key_value_it.next()) |key_or_value| {
|
||||||
switch (count) {
|
switch (count) {
|
||||||
@ -53,27 +53,27 @@ pub fn parse(self: *Self) !void {
|
|||||||
if (arrayParam(item.key)) |key| {
|
if (arrayParam(item.key)) |key| {
|
||||||
if (params.get(key)) |value| {
|
if (params.get(key)) |value| {
|
||||||
switch (value.*) {
|
switch (value.*) {
|
||||||
.array => try value.array.append(self.data.string(item.value)),
|
.array => try value.array.append(self.dataValue(item.value)),
|
||||||
else => return error.JetzigQueryParseError,
|
else => return error.JetzigQueryParseError,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var array = try self.data.createArray();
|
var array = try self.data.createArray();
|
||||||
try array.append(self.data.string(item.value));
|
try array.append(self.dataValue(item.value));
|
||||||
try params.put(key, array);
|
try params.put(key, array);
|
||||||
}
|
}
|
||||||
} else if (mappingParam(item.key)) |mapping| {
|
} else if (mappingParam(item.key)) |mapping| {
|
||||||
if (params.get(mapping.key)) |value| {
|
if (params.get(mapping.key)) |value| {
|
||||||
switch (value.*) {
|
switch (value.*) {
|
||||||
.object => try value.object.put(mapping.field, self.data.string(item.value)),
|
.object => try value.object.put(mapping.field, self.dataValue(item.value)),
|
||||||
else => return error.JetzigQueryParseError,
|
else => return error.JetzigQueryParseError,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var object = try self.data.createObject();
|
var object = try self.data.createObject();
|
||||||
try object.put(mapping.field, self.data.string(item.value));
|
try object.put(mapping.field, self.dataValue(item.value));
|
||||||
try params.put(mapping.key, object);
|
try params.put(mapping.key, object);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try params.put(item.key, self.data.string(item.value));
|
try params.put(item.key, self.dataValue(item.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,6 +103,14 @@ fn mappingParam(input: []const u8) ?struct { key: []const u8, field: []const u8
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dataValue(self: Query, value: ?[]const u8) *jetzig.data.Data.Value {
|
||||||
|
if (value) |item_value| {
|
||||||
|
return self.data.string(item_value);
|
||||||
|
} else {
|
||||||
|
return self.data._null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "simple query string" {
|
test "simple query string" {
|
||||||
const allocator = std.testing.allocator;
|
const allocator = std.testing.allocator;
|
||||||
const query_string = "foo=bar&baz=qux";
|
const query_string = "foo=bar&baz=qux";
|
||||||
@ -155,3 +163,26 @@ test "query string with mapping values" {
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "query string with param without value" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const query_string = "foo&bar";
|
||||||
|
var data = jetzig.data.Data.init(allocator);
|
||||||
|
|
||||||
|
var query = init(allocator, query_string, &data);
|
||||||
|
defer query.deinit();
|
||||||
|
|
||||||
|
try query.parse();
|
||||||
|
|
||||||
|
const foo = try data.get("foo");
|
||||||
|
try switch (foo.*) {
|
||||||
|
.Null => {},
|
||||||
|
else => std.testing.expect(false),
|
||||||
|
};
|
||||||
|
|
||||||
|
const bar = try data.get("bar");
|
||||||
|
try switch (bar.*) {
|
||||||
|
.Null => {},
|
||||||
|
else => std.testing.expect(false),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -146,6 +146,7 @@ fn renderHTML(
|
|||||||
if (route) |matched_route| {
|
if (route) |matched_route| {
|
||||||
const template = zmpl.find(matched_route.template);
|
const template = zmpl.find(matched_route.template);
|
||||||
if (template == null) {
|
if (template == null) {
|
||||||
|
request.response_data.noop(bool, false); // FIXME: Weird Zig bug ? Any call here fixes it.
|
||||||
if (try self.renderMarkdown(request, route)) |rendered_markdown| {
|
if (try self.renderMarkdown(request, route)) |rendered_markdown| {
|
||||||
return request.setResponse(rendered_markdown, .{});
|
return request.setResponse(rendered_markdown, .{});
|
||||||
}
|
}
|
||||||
@ -376,7 +377,7 @@ fn renderNotFound(request: *jetzig.http.Request) !RenderedView {
|
|||||||
fn renderBadRequest(request: *jetzig.http.Request) !RenderedView {
|
fn renderBadRequest(request: *jetzig.http.Request) !RenderedView {
|
||||||
request.response_data.reset();
|
request.response_data.reset();
|
||||||
|
|
||||||
const status: jetzig.http.StatusCode = .not_found;
|
const status: jetzig.http.StatusCode = .bad_request;
|
||||||
const content = try request.formatStatus(status);
|
const content = try request.formatStatus(status);
|
||||||
return .{
|
return .{
|
||||||
.view = jetzig.views.View{ .data = request.response_data, .status_code = status },
|
.view = jetzig.views.View{ .data = request.response_data, .status_code = status },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user