change interface to more closely match others in universal lambda
This commit is contained in:
parent
c44ad2ba84
commit
b058368285
|
@ -14,6 +14,11 @@ pub const Response = extern struct {
|
||||||
|
|
||||||
headers: [*]Header,
|
headers: [*]Header,
|
||||||
headers_len: usize,
|
headers_len: usize,
|
||||||
|
|
||||||
|
status: usize,
|
||||||
|
|
||||||
|
reason_ptr: [*]u8,
|
||||||
|
reason_len: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Request = extern struct {
|
pub const Request = extern struct {
|
||||||
|
@ -39,7 +44,7 @@ pub const ZigRequest = struct {
|
||||||
target: []const u8,
|
target: []const u8,
|
||||||
method: [:0]u8,
|
method: [:0]u8,
|
||||||
content: []u8,
|
content: []u8,
|
||||||
headers: []Header,
|
headers: std.http.Headers,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ZigHeader = struct {
|
pub const ZigHeader = struct {
|
||||||
|
@ -48,11 +53,33 @@ pub const ZigHeader = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ZigResponse = struct {
|
pub const ZigResponse = struct {
|
||||||
|
status: std.http.Status = .ok,
|
||||||
|
reason: ?[]const u8 = null,
|
||||||
body: *std.ArrayList(u8),
|
body: *std.ArrayList(u8),
|
||||||
headers: *std.StringHashMap([]const u8),
|
headers: std.http.Headers,
|
||||||
|
request: ZigRequest,
|
||||||
|
prepend: std.ArrayList(u8),
|
||||||
|
|
||||||
|
pub fn write(res: *ZigResponse, bytes: []const u8) !usize {
|
||||||
|
return res.prepend.writer().write(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeAll(res: *ZigResponse, bytes: []const u8) !void {
|
||||||
|
return res.prepend.writer().writeAll(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writer(res: *ZigResponse) std.io.Writer {
|
||||||
|
return res.prepend.writer().writer();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(res: *ZigResponse) !void {
|
||||||
|
if (res.prepend.items.len > 0)
|
||||||
|
try res.body.insertSlice(0, res.prepend.items);
|
||||||
|
res.prepend.deinit();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ZigRequestHandler = *const fn (std.mem.Allocator, ZigRequest, ZigResponse) anyerror!void;
|
pub const ZigRequestHandler = *const fn (std.mem.Allocator, *ZigResponse) anyerror!void;
|
||||||
|
|
||||||
/// This function is optional and can be exported by zig libraries for
|
/// This function is optional and can be exported by zig libraries for
|
||||||
/// initialization. If exported, it will be called once in the beginning of
|
/// initialization. If exported, it will be called once in the beginning of
|
||||||
|
@ -64,28 +91,25 @@ pub fn zigInit(parent_allocator: *anyopaque) callconv(.C) void {
|
||||||
allocator = @ptrCast(@alignCast(parent_allocator));
|
allocator = @ptrCast(@alignCast(parent_allocator));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toZigHeader(header: Header) ZigHeader {
|
|
||||||
return .{
|
|
||||||
.name = header.name_ptr[0..header.name_len],
|
|
||||||
.value = header.value_ptr[0..header.value_len],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a StringHashMap to the structure necessary for passing through the
|
/// Converts a StringHashMap to the structure necessary for passing through the
|
||||||
/// C boundary. This will be called automatically for you via the handleRequest function
|
/// C boundary. This will be called automatically for you via the handleRequest function
|
||||||
/// and is also used by the main processing loop to coerce request headers
|
/// and is also used by the main processing loop to coerce request headers
|
||||||
fn toHeaders(alloc: std.mem.Allocator, headers: std.StringHashMap([]const u8)) ![*]Header {
|
fn toHeaders(alloc: std.mem.Allocator, headers: std.http.Headers) ![*]Header {
|
||||||
var header_array = try std.ArrayList(Header).initCapacity(alloc, headers.count());
|
var header_array = try std.ArrayList(Header).initCapacity(alloc, headers.list.items.len);
|
||||||
var iterator = headers.iterator();
|
log.err("enter ({d})", .{headers.list.items.len});
|
||||||
while (iterator.next()) |kv| {
|
for (headers.list.items) |*field| {
|
||||||
|
// var name = try alloc.dupe(u8, field.name);
|
||||||
|
// var val = try alloc.dupe(u8, field.value);
|
||||||
|
// log.err(" response header name {s}, val {s}", .{ name, val });
|
||||||
header_array.appendAssumeCapacity(.{
|
header_array.appendAssumeCapacity(.{
|
||||||
.name_ptr = @constCast(kv.key_ptr.*).ptr,
|
.name_ptr = @constCast(field.name.ptr),
|
||||||
.name_len = kv.key_ptr.*.len,
|
.name_len = field.name.len,
|
||||||
|
|
||||||
.value_ptr = @constCast(kv.value_ptr.*).ptr,
|
.value_ptr = @constCast(field.value.ptr),
|
||||||
.value_len = kv.value_ptr.*.len,
|
.value_len = field.value.len,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
log.err("exit", .{});
|
||||||
return header_array.items.ptr;
|
return header_array.items.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,19 +128,43 @@ pub fn handleRequest(request: *Request, zigRequestHandler: ZigRequestHandler) ?*
|
||||||
var response = std.ArrayList(u8).init(alloc);
|
var response = std.ArrayList(u8).init(alloc);
|
||||||
|
|
||||||
// setup headers
|
// setup headers
|
||||||
var headers = std.StringHashMap([]const u8).init(alloc);
|
var response_headers = std.http.Headers.init(alloc);
|
||||||
zigRequestHandler(
|
var request_headers = std.http.Headers.init(alloc);
|
||||||
alloc,
|
for (0..request.headers_len) |i|
|
||||||
.{
|
request_headers.append(
|
||||||
|
request.headers[i].name_ptr[0..request.headers[i].name_len],
|
||||||
|
request.headers[i].value_ptr[0..request.headers[i].value_len],
|
||||||
|
) catch |e| {
|
||||||
|
log.err("Unexpected error processing request: {any}", .{e});
|
||||||
|
if (@errorReturnTrace()) |trace| {
|
||||||
|
std.debug.dumpStackTrace(trace.*);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// if (serve_result.prepended_request_data_len > 0) {
|
||||||
|
// var al = std.ArrayList(u8).initCapacity(allocator, slice.len + serve_result.prepended_request_data_len);
|
||||||
|
// defer al.deinit();
|
||||||
|
// al.appendSliceAssumeCapacity(serve_result.prepended_request_data[0..serve_result.prepended_request_data_len]);
|
||||||
|
// al.appendSliceAssumeCapacity(slice);
|
||||||
|
// slice = al.toOwnedSlice();
|
||||||
|
// }
|
||||||
|
|
||||||
|
var prepend = std.ArrayList(u8).init(alloc);
|
||||||
|
var zig_response = ZigResponse{
|
||||||
|
.headers = response_headers,
|
||||||
|
.body = &response,
|
||||||
|
.prepend = prepend,
|
||||||
|
.request = .{
|
||||||
|
.content = request.content[0..request.content_len],
|
||||||
.target = request.target[0..request.target_len],
|
.target = request.target[0..request.target_len],
|
||||||
.method = request.method[0..request.method_len :0],
|
.method = request.method[0..request.method_len :0],
|
||||||
.content = request.content[0..request.content_len],
|
.headers = request_headers,
|
||||||
.headers = request.headers[0..request.headers_len],
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.body = &response,
|
|
||||||
.headers = &headers,
|
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
zigRequestHandler(
|
||||||
|
alloc,
|
||||||
|
&zig_response,
|
||||||
) catch |e| {
|
) catch |e| {
|
||||||
log.err("Unexpected error processing request: {any}", .{e});
|
log.err("Unexpected error processing request: {any}", .{e});
|
||||||
if (@errorReturnTrace()) |trace| {
|
if (@errorReturnTrace()) |trace| {
|
||||||
|
@ -131,15 +179,27 @@ pub fn handleRequest(request: *Request, zigRequestHandler: ZigRequestHandler) ?*
|
||||||
log.err("Could not allocate memory for response object. This may be fatal", .{});
|
log.err("Could not allocate memory for response object. This may be fatal", .{});
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
zig_response.finish() catch {
|
||||||
|
log.err("Could not allocate memory for response object. This may be fatal", .{});
|
||||||
|
return null;
|
||||||
|
};
|
||||||
rc.ptr = response.items.ptr;
|
rc.ptr = response.items.ptr;
|
||||||
rc.len = response.items.len;
|
rc.len = response.items.len;
|
||||||
rc.headers = toHeaders(alloc, headers) catch |e| {
|
rc.headers = toHeaders(alloc, response_headers) catch |e| {
|
||||||
log.err("Unexpected error processing request: {any}", .{e});
|
log.err("Unexpected error processing request: {any}", .{e});
|
||||||
if (@errorReturnTrace()) |trace| {
|
if (@errorReturnTrace()) |trace| {
|
||||||
std.debug.dumpStackTrace(trace.*);
|
std.debug.dumpStackTrace(trace.*);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
rc.headers_len = headers.count();
|
//log.err("headers len: {d} header[0] name: {s}", .{ rc.headers_len, rc.headers[0].name_ptr[0..rc.headers[0].name_len] });
|
||||||
|
rc.headers_len = response_headers.list.items.len;
|
||||||
|
rc.status = if (zig_response.status == .ok) 0 else @intFromEnum(zig_response.status);
|
||||||
|
rc.reason_len = 0;
|
||||||
|
if (zig_response.reason) |*r| {
|
||||||
|
rc.reason_ptr = @constCast(r.ptr);
|
||||||
|
rc.reason_len = r.len;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,27 +57,31 @@ export fn handle_request(request: *interface.Request) callconv(.C) ?*interface.R
|
||||||
//
|
//
|
||||||
// handleRequest function here is the last line of boilerplate and the
|
// handleRequest function here is the last line of boilerplate and the
|
||||||
// entry to a request
|
// entry to a request
|
||||||
fn handleRequest(allocator: std.mem.Allocator, request: interface.ZigRequest, response: interface.ZigResponse) !void {
|
fn handleRequest(allocator: std.mem.Allocator, response: *interface.ZigResponse) !void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
// setup
|
// setup
|
||||||
var response_writer = response.body.writer();
|
var response_writer = response.body.writer();
|
||||||
// real work
|
// real work
|
||||||
for (request.headers) |h| {
|
if (response.request.headers.getFirstValue("host")) |host| {
|
||||||
const header = interface.toZigHeader(h);
|
if (std.mem.startsWith(u8, host, "iam")) {
|
||||||
// std.debug.print("\n{s}: {s}\n", .{ header.name, header.value });
|
|
||||||
if (std.ascii.eqlIgnoreCase(header.name, "host") and std.mem.startsWith(u8, header.value, "iam")) {
|
|
||||||
try response_writer.print("iam response", .{});
|
try response_writer.print("iam response", .{});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (std.ascii.eqlIgnoreCase(header.name, "x-slow")) {
|
}
|
||||||
std.time.sleep(std.time.ns_per_ms * (std.fmt.parseInt(usize, header.value, 10) catch 1000));
|
if (response.request.headers.getFirstValue("x-slow")) |ms| {
|
||||||
|
std.time.sleep(std.time.ns_per_ms * (std.fmt.parseInt(usize, ms, 10) catch 1000));
|
||||||
try response_writer.print("i am slow\n\n", .{});
|
try response_writer.print("i am slow\n\n", .{});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (response.request.headers.getFirstValue("x-log-this")) |l| {
|
||||||
|
try response.writeAll(l);
|
||||||
}
|
}
|
||||||
try response_writer.print(" {d}", .{request.headers.len});
|
if (response.request.headers.getFirstValue("x-status")) |s| {
|
||||||
try response.headers.put("X-custom-foo", "bar");
|
response.status = @enumFromInt(std.fmt.parseInt(u10, s, 10) catch 500);
|
||||||
log.info("handlerequest header count {d}", .{response.headers.count()});
|
}
|
||||||
|
try response_writer.print(" {d}", .{response.request.headers.list.items.len});
|
||||||
|
try response.headers.append("X-custom-foo", "bar");
|
||||||
|
log.info("handlerequest header count {d}", .{response.headers.list.items.len});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "handle_request" {
|
test "handle_request" {
|
||||||
|
@ -103,6 +107,7 @@ test "handle_request" {
|
||||||
};
|
};
|
||||||
const response = handle_request(&req).?;
|
const response = handle_request(&req).?;
|
||||||
try testing.expectEqualStrings(" 1", response.ptr[0..response.len]);
|
try testing.expectEqualStrings(" 1", response.ptr[0..response.len]);
|
||||||
|
try testing.expectEqual(@as(usize, 1), response.headers_len);
|
||||||
try testing.expectEqualStrings("X-custom-foo", response.headers[0].name_ptr[0..response.headers[0].name_len]);
|
try testing.expectEqualStrings("X-custom-foo", response.headers[0].name_ptr[0..response.headers[0].name_len]);
|
||||||
try testing.expectEqualStrings("bar", response.headers[0].value_ptr[0..response.headers[0].value_len]);
|
try testing.expectEqualStrings("bar", response.headers[0].value_ptr[0..response.headers[0].value_len]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,12 @@ fn serve(allocator: *std.mem.Allocator, response: *std.http.Server.Response) !*F
|
||||||
var slice: []u8 = serve_result.ptr[0..serve_result.len];
|
var slice: []u8 = serve_result.ptr[0..serve_result.len];
|
||||||
log.debug("response body: {s}", .{slice});
|
log.debug("response body: {s}", .{slice});
|
||||||
|
|
||||||
|
if (serve_result.status != 0) {
|
||||||
|
response.status = @enumFromInt(serve_result.status);
|
||||||
|
if (serve_result.reason_len > 0) {
|
||||||
|
response.reason = serve_result.reason_ptr[0..serve_result.reason_len];
|
||||||
|
}
|
||||||
|
}
|
||||||
// Deal with results
|
// Deal with results
|
||||||
var content_type_added = false;
|
var content_type_added = false;
|
||||||
for (0..serve_result.headers_len) |inx| {
|
for (0..serve_result.headers_len) |inx| {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user