add helper tests/change header helper to get all headers
Some checks failed
AWS-Zig Build / build-zig-0.11.0-amd64-host (push) Failing after 1m31s
Some checks failed
AWS-Zig Build / build-zig-0.11.0-amd64-host (push) Failing after 1m31s
This commit is contained in:
parent
346bd1d084
commit
1d0da7c80f
27
build.zig
27
build.zig
|
@ -53,11 +53,38 @@ pub fn build(b: *std.Build) !void {
|
||||||
var run_main_tests = b.addRunArtifact(main_tests);
|
var run_main_tests = b.addRunArtifact(main_tests);
|
||||||
run_main_tests.skip_foreign_checks = true;
|
run_main_tests.skip_foreign_checks = true;
|
||||||
|
|
||||||
|
const helper_tests = b.addTest(.{
|
||||||
|
.root_source_file = .{ .path = "src/helpers.zig" },
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
_ = try ulb.createOptionsModule(b, helper_tests);
|
||||||
|
// Add module
|
||||||
|
helper_tests.addAnonymousModule("universal_lambda_handler", .{
|
||||||
|
// Source file can be anywhere on disk, does not need to be a subdirectory
|
||||||
|
.source_file = .{ .path = "src/universal_lambda.zig" },
|
||||||
|
// We alsso need the interface module available here
|
||||||
|
.dependencies = &[_]std.Build.ModuleDependency{
|
||||||
|
// Add options module so we can let our universal_lambda know what
|
||||||
|
// type of interface is necessary
|
||||||
|
.{
|
||||||
|
.name = "build_options",
|
||||||
|
.module = main_tests.modules.get("build_options").?,
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.name = "flexilib-interface",
|
||||||
|
.module = flexilib_module,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
var run_helper_tests = b.addRunArtifact(helper_tests);
|
||||||
|
|
||||||
// This creates a build step. It will be visible in the `zig build --help` menu,
|
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||||
// and can be selected like this: `zig build test`
|
// and can be selected like this: `zig build test`
|
||||||
// This will evaluate the `test` step rather than the default, which is "install".
|
// This will evaluate the `test` step rather than the default, which is "install".
|
||||||
const test_step = b.step("test", "Run library tests");
|
const test_step = b.step("test", "Run library tests");
|
||||||
test_step.dependOn(&run_main_tests.step);
|
test_step.dependOn(&run_main_tests.step);
|
||||||
|
test_step.dependOn(&run_helper_tests.step);
|
||||||
|
|
||||||
_ = b.addModule("universal_lambda_helpers", .{
|
_ = b.addModule("universal_lambda_helpers", .{
|
||||||
.source_file = .{ .path = "src/helpers.zig" },
|
.source_file = .{ .path = "src/helpers.zig" },
|
||||||
|
|
|
@ -55,22 +55,61 @@ fn findTargetWithoutContext(allocator: std.mem.Allocator) ![]const u8 {
|
||||||
return "/";
|
return "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getFirstHeaderValue(allocator: std.mem.Allocator, context: universal_lambda.Context, header_name: []const u8) !?[]const u8 {
|
pub const Headers = struct {
|
||||||
|
http_headers: *std.http.Headers,
|
||||||
|
owned: bool,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator, headers: *std.http.Headers, owned: bool) Self {
|
||||||
|
return .{
|
||||||
|
.http_headers = headers,
|
||||||
|
.owned = owned,
|
||||||
|
.allocator = allocator,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
if (self.owned) {
|
||||||
|
self.http_headers.deinit();
|
||||||
|
self.allocator.destroy(self.http_headers);
|
||||||
|
self.http_headers = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get headers from request. If Lambda is not in a web context, headers
|
||||||
|
/// will be gathered from the command line and include all environment variables
|
||||||
|
pub fn allHeaders(allocator: std.mem.Allocator, context: universal_lambda.Context) !Headers {
|
||||||
switch (context) {
|
switch (context) {
|
||||||
.web_request => |res| return res.request.headers.getFirstValue(header_name),
|
.web_request => |res| return Headers.init(allocator, &res.request.headers, false),
|
||||||
.flexilib => |ctx| {
|
.flexilib => |ctx| {
|
||||||
|
var headers = try allocator.create(std.http.Headers);
|
||||||
|
errdefer allocator.destroy(headers);
|
||||||
|
headers.allocator = allocator;
|
||||||
|
headers.list = .{};
|
||||||
|
headers.index = .{};
|
||||||
|
headers.owned = true;
|
||||||
|
errdefer headers.deinit();
|
||||||
for (ctx.request.headers) |hdr| {
|
for (ctx.request.headers) |hdr| {
|
||||||
if (std.ascii.eqlIgnoreCase(hdr.name_ptr[0..hdr.name_len], header_name)) {
|
try headers.append(hdr.name_ptr[0..hdr.name_len], hdr.value_ptr[0..hdr.value_len]);
|
||||||
return hdr.value_ptr[0..hdr.value_len];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return Headers.init(allocator, headers, true);
|
||||||
},
|
},
|
||||||
.none => return findHeaderWithoutContext(allocator, header_name),
|
.none => return headersWithoutContext(allocator),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn findHeaderWithoutContext(allocator: std.mem.Allocator, header_name: []const u8) !?[]const u8 {
|
fn headersWithoutContext(allocator: std.mem.Allocator) !Headers {
|
||||||
|
var headers = try allocator.create(std.http.Headers);
|
||||||
|
errdefer allocator.destroy(headers);
|
||||||
|
headers.allocator = allocator;
|
||||||
|
headers.list = .{};
|
||||||
|
headers.index = .{};
|
||||||
|
headers.owned = true;
|
||||||
|
errdefer headers.deinit();
|
||||||
|
|
||||||
// without context, we have environment variables
|
// without context, we have environment variables
|
||||||
// possibly event data (API Gateway does this if so configured),
|
// possibly event data (API Gateway does this if so configured),
|
||||||
// or the command line. For headers, we'll prioritize command line options
|
// or the command line. For headers, we'll prioritize command line options
|
||||||
|
@ -85,11 +124,12 @@ fn findHeaderWithoutContext(allocator: std.mem.Allocator, header_name: []const u
|
||||||
{
|
{
|
||||||
return error.CommandLineError;
|
return error.CommandLineError;
|
||||||
}
|
}
|
||||||
|
is_header_option = false;
|
||||||
var split = std.mem.splitSequence(u8, arg, "=");
|
var split = std.mem.splitSequence(u8, arg, "=");
|
||||||
const name = split.next().?;
|
const name = split.next().?;
|
||||||
if (!std.ascii.eqlIgnoreCase(name, header_name)) continue;
|
if (split.next()) |s| {
|
||||||
if (split.next()) |s| return s; // found it
|
try headers.append(name, s);
|
||||||
continue; // bad format, but we're not returning errors. We can cope with this one though
|
} else return error.CommandLineError;
|
||||||
}
|
}
|
||||||
if (std.mem.startsWith(u8, arg, "-" ++ header_option.short) or
|
if (std.mem.startsWith(u8, arg, "-" ++ header_option.short) or
|
||||||
std.mem.startsWith(u8, arg, "--" ++ header_option.long))
|
std.mem.startsWith(u8, arg, "--" ++ header_option.long))
|
||||||
|
@ -106,11 +146,26 @@ fn findHeaderWithoutContext(allocator: std.mem.Allocator, header_name: []const u
|
||||||
defer map.deinit();
|
defer map.deinit();
|
||||||
var it = map.iterator();
|
var it = map.iterator();
|
||||||
while (it.next()) |kvp| {
|
while (it.next()) |kvp| {
|
||||||
// TODO: This is the only place where allocation is necessary. This
|
// Do not allow environment variables to interfere with command line
|
||||||
// will work, because in reality there is always an area allocator passed
|
if (headers.getFirstValue(kvp.key_ptr.*) == null)
|
||||||
// to us. But if there's not....
|
try headers.append(
|
||||||
if (std.ascii.eqlIgnoreCase(kvp.key_ptr.*, header_name))
|
kvp.key_ptr.*,
|
||||||
return try allocator.dupe(u8, kvp.value_ptr.*);
|
kvp.value_ptr.*,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return null; // nowhere to be found
|
return Headers.init(allocator, headers, true); // nowhere to be found
|
||||||
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
std.testing.refAllDecls(@This());
|
||||||
|
}
|
||||||
|
|
||||||
|
test "can get headers" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const context = universal_lambda.Context{
|
||||||
|
.none = {},
|
||||||
|
};
|
||||||
|
var headers = try allHeaders(allocator, context);
|
||||||
|
defer headers.deinit();
|
||||||
|
try std.testing.expect(headers.http_headers.list.items.len > 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user