diff --git a/src/interface.zig b/src/interface.zig index 588539f..8969404 100644 --- a/src/interface.zig +++ b/src/interface.zig @@ -96,11 +96,7 @@ pub fn zigInit(parent_allocator: *anyopaque) callconv(.C) void { /// and is also used by the main processing loop to coerce request headers fn toHeaders(alloc: std.mem.Allocator, headers: std.http.Headers) ![*]Header { var header_array = try std.ArrayList(Header).initCapacity(alloc, headers.list.items.len); - log.err("enter ({d})", .{headers.list.items.len}); 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(.{ .name_ptr = @constCast(field.name.ptr), .name_len = field.name.len, @@ -109,7 +105,6 @@ fn toHeaders(alloc: std.mem.Allocator, headers: std.http.Headers) ![*]Header { .value_len = field.value.len, }); } - log.err("exit", .{}); return header_array.items.ptr; } @@ -128,7 +123,6 @@ pub fn handleRequest(request: *Request, zigRequestHandler: ZigRequestHandler) ?* var response = std.ArrayList(u8).init(alloc); // setup headers - var response_headers = std.http.Headers.init(alloc); var request_headers = std.http.Headers.init(alloc); for (0..request.headers_len) |i| request_headers.append( @@ -142,17 +136,9 @@ pub fn handleRequest(request: *Request, zigRequestHandler: ZigRequestHandler) ?* 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, + .headers = .{ .allocator = alloc }, .body = &response, .prepend = prepend, .request = .{ @@ -170,11 +156,16 @@ pub fn handleRequest(request: *Request, zigRequestHandler: ZigRequestHandler) ?* if (@errorReturnTrace()) |trace| { std.debug.dumpStackTrace(trace.*); } - return null; + if (zig_response.status == .ok) // this was an unexpected throw + zig_response.status = .internal_server_error; + return buildResponse(alloc, &zig_response); }; // Marshall data back for handling by server + return buildResponse(alloc, &zig_response); +} +fn buildResponse(alloc: std.mem.Allocator, zig_response: *ZigResponse) ?*Response { var rc = alloc.create(Response) catch { log.err("Could not allocate memory for response object. This may be fatal", .{}); return null; @@ -183,23 +174,22 @@ pub fn handleRequest(request: *Request, zigRequestHandler: ZigRequestHandler) ?* log.err("Could not allocate memory for response object. This may be fatal", .{}); return null; }; - rc.ptr = response.items.ptr; - rc.len = response.items.len; - rc.headers = toHeaders(alloc, response_headers) catch |e| { + + rc.ptr = zig_response.body.items.ptr; + rc.len = zig_response.body.items.len; + rc.headers = toHeaders(alloc, zig_response.headers) catch |e| { log.err("Unexpected error processing request: {any}", .{e}); if (@errorReturnTrace()) |trace| { std.debug.dumpStackTrace(trace.*); } return null; }; - //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.headers_len = zig_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; } diff --git a/src/main-lib.zig b/src/main-lib.zig index d05fd67..2053b4d 100644 --- a/src/main-lib.zig +++ b/src/main-lib.zig @@ -79,9 +79,11 @@ fn handleRequest(allocator: std.mem.Allocator, response: *interface.ZigResponse) if (response.request.headers.getFirstValue("x-status")) |s| { response.status = @enumFromInt(std.fmt.parseInt(u10, s, 10) catch 500); } + if (response.request.headers.getFirstValue("x-throw")) |_| { + return error.Thrown; + } 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" { @@ -103,7 +105,7 @@ test "handle_request" { .content = @ptrCast(@constCast("GET".ptr)), .content_len = 3, .headers = headers.ptr, - .headers_len = 1, + .headers_len = headers.len, }; const response = handle_request(&req).?; try testing.expectEqualStrings(" 1", response.ptr[0..response.len]); @@ -111,3 +113,96 @@ test "handle_request" { 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]); } + +test "lib can write data directly" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + var aa = arena.allocator(); + interface.zigInit(&aa); + var headers: []interface.Header = @constCast(&[_]interface.Header{.{ + .name_ptr = @ptrCast(@constCast("x-log-this".ptr)), + .name_len = "x-log-this".len, + .value_ptr = @ptrCast(@constCast("I am a teapot".ptr)), + .value_len = "I am a teapot".len, + }}); + var req = interface.Request{ + .target = @ptrCast(@constCast("/".ptr)), + .target_len = 1, + .method = @ptrCast(@constCast("GET".ptr)), + .method_len = 3, + .content = @ptrCast(@constCast("GET".ptr)), + .content_len = 3, + .headers = headers.ptr, + .headers_len = headers.len, + }; + const response = handle_request(&req).?; + 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("bar", response.headers[0].value_ptr[0..response.headers[0].value_len]); + try testing.expectEqualStrings("I am a teapot 1", response.ptr[0..response.len]); +} +test "lib can write data directly and still throw" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + var aa = arena.allocator(); + interface.zigInit(&aa); + var headers: []interface.Header = @constCast(&[_]interface.Header{ .{ + .name_ptr = @ptrCast(@constCast("x-log-this".ptr)), + .name_len = "x-log-this".len, + .value_ptr = @ptrCast(@constCast("I am a teapot".ptr)), + .value_len = "I am a teapot".len, + }, .{ + .name_ptr = @ptrCast(@constCast("x-throw".ptr)), + .name_len = "x-throw".len, + .value_ptr = @ptrCast(@constCast("I am a teapot".ptr)), + .value_len = "I am a teapot".len, + } }); + var req = interface.Request{ + .target = @ptrCast(@constCast("/".ptr)), + .target_len = 1, + .method = @ptrCast(@constCast("GET".ptr)), + .method_len = 3, + .content = @ptrCast(@constCast("GET".ptr)), + .content_len = 3, + .headers = headers.ptr, + .headers_len = headers.len, + }; + const response = handle_request(&req).?; + try testing.expectEqual(@as(usize, 500), response.status); + try testing.expectEqualStrings("I am a teapot", response.ptr[0..response.len]); +} +test "lib can set status, update data directly and still throw" { + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); + defer arena.deinit(); + var aa = arena.allocator(); + interface.zigInit(&aa); + var headers: []interface.Header = @constCast(&[_]interface.Header{ .{ + .name_ptr = @ptrCast(@constCast("x-log-this".ptr)), + .name_len = "x-log-this".len, + .value_ptr = @ptrCast(@constCast("I am a teapot".ptr)), + .value_len = "I am a teapot".len, + }, .{ + .name_ptr = @ptrCast(@constCast("x-throw".ptr)), + .name_len = "x-throw".len, + .value_ptr = @ptrCast(@constCast("I am a teapot".ptr)), + .value_len = "I am a teapot".len, + }, .{ + .name_ptr = @ptrCast(@constCast("x-status".ptr)), + .name_len = "x-status".len, + .value_ptr = @ptrCast(@constCast("418".ptr)), + .value_len = "418".len, + } }); + var req = interface.Request{ + .target = @ptrCast(@constCast("/".ptr)), + .target_len = 1, + .method = @ptrCast(@constCast("GET".ptr)), + .method_len = 3, + .content = @ptrCast(@constCast("GET".ptr)), + .content_len = 3, + .headers = headers.ptr, + .headers_len = headers.len, + }; + const response = handle_request(&req).?; + try testing.expectEqual(@as(usize, 418), response.status); + try testing.expectEqualStrings("I am a teapot", response.ptr[0..response.len]); +} diff --git a/src/main.zig b/src/main.zig index 377114f..56a3184 100644 --- a/src/main.zig +++ b/src/main.zig @@ -625,6 +625,7 @@ test { std.testing.refAllDecls(@This()); std.testing.refAllDecls(config); std.testing.refAllDecls(interface); + std.testing.refAllDecls(@import("main-lib.zig")); } var test_resp_buf: [1024]u8 = undefined; var test_resp_buf_len: usize = undefined;