universal-lambda-zig/src/awslambda.zig

83 lines
3.1 KiB
Zig

const std = @import("std");
const interface = @import("universal_lambda_interface");
const lambda_zig = @import("aws_lambda_runtime");
const log = std.log.scoped(.awslambda);
threadlocal var universal_handler: interface.HandlerFn = undefined;
/// This is called by the aws lambda runtime (our import), and must
/// call the universal handler (our downstream client). The main job here
/// is to convert signatures, ore more specifically, build out the context
/// that the universal handler is expecting
fn lambdaHandler(arena: std.mem.Allocator, event_data: []const u8) ![]const u8 {
const response_body: std.ArrayList(u8) = std.ArrayList(u8).init(arena);
// Marshal lambda_zig data into a context
// TODO: Maybe this should parse API Gateway data into a proper response
// TODO: environment variables -> Headers?
var response = interface.Response{
.allocator = arena,
.headers = &.{},
.body = response_body,
.request = .{
.headers = &.{},
},
};
// Call back to the handler that we were given
const result = universal_handler(arena, event_data, &response);
// TODO: If our universal handler writes to the response body, we should
// handle that in a consistent way
// Return result from our handler back to AWS lambda via the lambda module
return result;
}
// AWS lambda zig handler: const HandlerFn = *const fn (std.mem.Allocator, []const u8) anyerror![]const u8;
// Our handler: pub const HandlerFn = *const fn (std.mem.Allocator, []const u8, Context) anyerror![]const u8;
pub fn run(allocator: ?std.mem.Allocator, event_handler: interface.HandlerFn) !u8 {
universal_handler = event_handler;
// pub fn run(allocator: ?std.mem.Allocator, event_handler: HandlerFn) !void { // TODO: remove inferred error set?
try lambda_zig.run(allocator, lambdaHandler);
return 0;
}
fn handler(allocator: std.mem.Allocator, event_data: []const u8) ![]const u8 {
_ = allocator;
return event_data;
}
////////////////////////////////////////////////////////////////////////
// All code below this line is for testing
////////////////////////////////////////////////////////////////////////
test {
std.testing.refAllDecls(lambda_zig);
}
test "basic request" {
// std.testing.log_level = .debug;
const allocator = std.testing.allocator;
const request =
\\{"foo": "bar", "baz": "qux"}
;
// This is what's actually coming back. Is this right?
const expected_response =
\\nothing but net
;
const TestHandler = struct {
pub fn handler(alloc: std.mem.Allocator, event_data: []const u8, context: interface.Context) ![]const u8 {
_ = alloc;
_ = event_data;
_ = context;
log.debug("in handler", .{});
return "nothing but net";
}
};
universal_handler = TestHandler.handler;
const lambda_response = try lambda_zig.test_lambda_request(allocator, request, 1, lambdaHandler);
defer lambda_zig.deinit();
defer allocator.free(lambda_response);
try std.testing.expectEqualStrings(expected_response, lambda_response);
}