1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2025-10-20 15:14:08 +00:00

access raw query params w/o allocator, close #40

This commit is contained in:
Rene Schallner 2024-02-22 22:44:04 +01:00
parent 42e96b4875
commit 680e981d13
3 changed files with 124 additions and 8 deletions

View file

@ -47,6 +47,27 @@ pub fn main() !void {
const param_count = r.getParamCount();
std.log.info("param_count: {}", .{param_count});
// ================================================================
// Access RAW params from querystring
// ================================================================
// let's get param "one" by name
std.debug.print("\n", .{});
if (r.getParamSlice("one")) |maybe_str| {
std.log.info("Param one = {s}", .{maybe_str});
} else {
std.log.info("Param one not found!", .{});
}
var arg_it = r.getParamSlices();
while (arg_it.next()) |param| {
std.log.info("ParamStr `{s}` is `{s}`", .{ param.name, param.value });
}
// ================================================================
// Access DECODED and typed params
// ================================================================
// iterate over all params as strings
var strparams = r.parametersToOwnedStrList(alloc, false) catch unreachable;
defer strparams.deinit();
@ -82,15 +103,10 @@ pub fn main() !void {
}
// check if we received a terminate=true parameter
if (r.getParamStr(alloc, "terminate", false)) |maybe_str| {
if (maybe_str) |*s| {
defer s.deinit();
if (std.mem.eql(u8, s.str, "true")) {
zap.stop();
}
if (r.getParamSlice("terminate")) |maybe_str| {
if (std.mem.eql(u8, maybe_str, "true")) {
zap.stop();
}
} else |err| {
std.log.err("cannot check for terminate param: {any}\n", .{err});
}
}
};

View file

@ -737,3 +737,59 @@ pub fn getParamStr(self: *const Self, a: std.mem.Allocator, name: []const u8, al
}
return try util.fio2strAllocOrNot(a, value, always_alloc);
}
/// similar to getParamStr, except it will return the part of the querystring
/// after the equals sign, non-decoded, and always as character slice.
/// - no allocation!
/// - does not requre parseQuery() or anything to be called in advance
pub fn getParamSlice(self: *const Self, name: []const u8) ?[]const u8 {
if (self.query) |query| {
var amp_it = std.mem.tokenizeScalar(u8, query, '&');
while (amp_it.next()) |maybe_pair| {
if (std.mem.indexOfScalar(u8, maybe_pair, '=')) |pos_of_eq| {
const pname = maybe_pair[0..pos_of_eq];
if (std.mem.eql(u8, pname, name)) {
if (maybe_pair.len > pos_of_eq) {
const pval = maybe_pair[pos_of_eq + 1 ..];
return pval;
}
}
}
}
}
return null;
}
pub const ParameterSlices = struct { name: []const u8, value: []const u8 };
pub const ParamSliceIterator = struct {
amp_it: std.mem.TokenIterator(u8, .scalar),
pub fn init(query: []const u8) @This() {
// const query = r.query orelse "";
return .{
.amp_it = std.mem.tokenizeScalar(u8, query, '&'),
};
}
pub fn next(self: *@This()) ?ParameterSlices {
while (self.amp_it.next()) |maybe_pair| {
if (std.mem.indexOfScalar(u8, maybe_pair, '=')) |pos_of_eq| {
const pname = maybe_pair[0..pos_of_eq];
if (maybe_pair.len > pos_of_eq) {
const pval = maybe_pair[pos_of_eq + 1 ..];
return .{ .name = pname, .value = pval };
}
}
}
return null;
}
};
/// Returns an iterator that yields all query parameters on next() in the
/// form of a ParameterSlices struct { .name, .value }
/// As with getParamSlice(), the value is not decoded
pub fn getParamSlices(self: *const Self) ParamSliceIterator {
const query = self.query orelse "";
return ParamSliceIterator.init(query);
}

View file

@ -33,6 +33,8 @@ test "http parameters" {
var strParams: ?zap.Request.HttpParamStrKVList = null;
var params: ?zap.Request.HttpParamKVList = null;
var paramOneStr: ?zap.FreeOrNot = null;
var paramOneSlice: ?[]const u8 = null;
var paramSlices: zap.Request.ParamSliceIterator = undefined;
pub fn on_request(r: zap.Request) void {
ran = true;
@ -49,6 +51,14 @@ test "http parameters" {
if (maybe_str) |*s| {
paramOneStr = s.*;
}
paramOneSlice = blk: {
if (r.getParamSlice("one")) |val| break :blk alloc.dupe(u8, val) catch unreachable;
break :blk null;
};
// paramSlices = zap.Request.ParamSliceIterator.init(r);
paramSlices = r.getParamSlices();
}
};
@ -85,12 +95,18 @@ test "http parameters" {
// allocator.free(p);
p.deinit();
}
if (Handler.paramOneSlice) |p| {
Handler.alloc.free(p);
}
}
try std.testing.expectEqual(Handler.ran, true);
try std.testing.expectEqual(Handler.param_count, 5);
try std.testing.expect(Handler.paramOneStr != null);
try std.testing.expectEqualStrings(Handler.paramOneStr.?.str, "1");
try std.testing.expect(Handler.paramOneSlice != null);
try std.testing.expectEqualStrings(Handler.paramOneSlice.?, "1");
try std.testing.expect(Handler.strParams != null);
for (Handler.strParams.?.items, 0..) |kv, i| {
switch (i) {
@ -118,6 +134,34 @@ test "http parameters" {
}
}
var pindex: usize = 0;
while (Handler.paramSlices.next()) |param| {
switch (pindex) {
0 => {
try std.testing.expectEqualStrings(param.name, "one");
try std.testing.expectEqualStrings(param.value, "1");
},
1 => {
try std.testing.expectEqualStrings(param.name, "two");
try std.testing.expectEqualStrings(param.value, "2");
},
2 => {
try std.testing.expectEqualStrings(param.name, "string");
try std.testing.expectEqualStrings(param.value, "hello+world");
},
3 => {
try std.testing.expectEqualStrings(param.name, "float");
try std.testing.expectEqualStrings(param.value, "6.28");
},
4 => {
try std.testing.expectEqualStrings(param.name, "bool");
try std.testing.expectEqualStrings(param.value, "true");
},
else => return error.TooManyArgs,
}
pindex += 1;
}
for (Handler.params.?.items, 0..) |kv, i| {
switch (i) {
0 => {