diff --git a/src/http/middleware.zig b/src/http/middleware.zig index 190a60d..ca805fd 100644 --- a/src/http/middleware.zig +++ b/src/http/middleware.zig @@ -715,7 +715,7 @@ pub fn ParseBody(comptime Body: type, comptime options: ParseBodyOptions) type { } }; } -pub fn parseBody(comptime Body: type) ParseBody(Body) { +pub fn parseBody(comptime Body: type, comptime options: ParseBodyOptions) ParseBody(Body, options) { return .{}; } @@ -752,7 +752,7 @@ test "parseBody" { var headers = http.Fields.init(std.testing.allocator); defer headers.deinit(); - try parseBody(Struct).handle( + try parseBody(Struct, .{}).handle( .{ .body = @as(?std.io.StreamSource, stream), .headers = headers }, .{}, .{ .allocator = std.testing.allocator }, diff --git a/src/http/multipart.zig b/src/http/multipart.zig index 854b7c3..e4c3880 100644 --- a/src/http/multipart.zig +++ b/src/http/multipart.zig @@ -357,6 +357,6 @@ test "parseFormData" { var src = std.io.StreamSource{ .const_buffer = std.io.fixedBufferStream(body) }; const val = try parseFormData(struct { foo: []const u8, - }, "abcd", src.reader(), std.testing.allocator); + }, false, "abcd", src.reader(), std.testing.allocator); util.deepFree(std.testing.allocator, val); } diff --git a/src/http/urlencode.zig b/src/http/urlencode.zig index fdfb680..c841717 100644 --- a/src/http/urlencode.zig +++ b/src/http/urlencode.zig @@ -252,49 +252,49 @@ fn formatQuery(comptime prefix: []const u8, params: anytype, writer: anytype) !v test "parse" { const testCase = struct { - fn case(comptime T: type, expected: T, query_string: []const u8) !void { - const result = try parse(std.testing.allocator, T, query_string); + fn case(allow_unknown_fields: bool, comptime T: type, expected: T, query_string: []const u8) !void { + const result = try parse(std.testing.allocator, allow_unknown_fields, T, query_string); defer parseFree(std.testing.allocator, result); try util.testing.expectDeepEqual(expected, result); } }.case; - try testCase(struct { int: usize = 3 }, .{ .int = 3 }, ""); - try testCase(struct { int: usize = 3 }, .{ .int = 2 }, "int=2"); - try testCase(struct { int: usize = 3 }, .{ .int = 2 }, "int=2&"); - try testCase(struct { boolean: bool = false }, .{ .boolean = false }, ""); - try testCase(struct { boolean: bool = false }, .{ .boolean = true }, "boolean"); - try testCase(struct { boolean: bool = false }, .{ .boolean = true }, "boolean=true"); - try testCase(struct { boolean: bool = false }, .{ .boolean = true }, "boolean=y"); - try testCase(struct { boolean: bool = false }, .{ .boolean = false }, "boolean=f"); - try testCase(struct { boolean: bool = false }, .{ .boolean = false }, "boolean=no"); - try testCase(struct { str_enum: ?enum { foo, bar } = null }, .{ .str_enum = null }, ""); - try testCase(struct { str_enum: ?enum { foo, bar } = null }, .{ .str_enum = .foo }, "str_enum=foo"); - try testCase(struct { str_enum: ?enum { foo, bar } = null }, .{ .str_enum = .bar }, "str_enum=bar"); - try testCase(struct { str_enum: ?enum { foo, bar } = .foo }, .{ .str_enum = .foo }, ""); - try testCase(struct { str_enum: ?enum { foo, bar } = .foo }, .{ .str_enum = null }, "str_enum"); - try testCase(struct { n1: usize = 5, n2: usize = 5 }, .{ .n1 = 1, .n2 = 2 }, "n1=1&n2=2"); - try testCase(struct { n1: usize = 5, n2: usize = 5 }, .{ .n1 = 1, .n2 = 2 }, "n1=1&n2=2&"); - try testCase(struct { n1: usize = 5, n2: usize = 5 }, .{ .n1 = 1, .n2 = 2 }, "n1=1&&n2=2&"); + try testCase(false, struct { int: usize = 3 }, .{ .int = 3 }, ""); + try testCase(false, struct { int: usize = 3 }, .{ .int = 2 }, "int=2"); + try testCase(false, struct { int: usize = 3 }, .{ .int = 2 }, "int=2&"); + try testCase(false, struct { boolean: bool = false }, .{ .boolean = false }, ""); + try testCase(false, struct { boolean: bool = false }, .{ .boolean = true }, "boolean"); + try testCase(false, struct { boolean: bool = false }, .{ .boolean = true }, "boolean=true"); + try testCase(false, struct { boolean: bool = false }, .{ .boolean = true }, "boolean=y"); + try testCase(false, struct { boolean: bool = false }, .{ .boolean = false }, "boolean=f"); + try testCase(false, struct { boolean: bool = false }, .{ .boolean = false }, "boolean=no"); + try testCase(false, struct { str_enum: ?enum { foo, bar } = null }, .{ .str_enum = null }, ""); + try testCase(false, struct { str_enum: ?enum { foo, bar } = null }, .{ .str_enum = .foo }, "str_enum=foo"); + try testCase(false, struct { str_enum: ?enum { foo, bar } = null }, .{ .str_enum = .bar }, "str_enum=bar"); + try testCase(false, struct { str_enum: ?enum { foo, bar } = .foo }, .{ .str_enum = .foo }, ""); + try testCase(false, struct { str_enum: ?enum { foo, bar } = .foo }, .{ .str_enum = null }, "str_enum"); + try testCase(false, struct { n1: usize = 5, n2: usize = 5 }, .{ .n1 = 1, .n2 = 2 }, "n1=1&n2=2"); + try testCase(false, struct { n1: usize = 5, n2: usize = 5 }, .{ .n1 = 1, .n2 = 2 }, "n1=1&n2=2&"); + try testCase(false, struct { n1: usize = 5, n2: usize = 5 }, .{ .n1 = 1, .n2 = 2 }, "n1=1&&n2=2&"); - try testCase(struct { str: ?[]const u8 = null }, .{ .str = null }, ""); - try testCase(struct { str: ?[]const u8 = null }, .{ .str = null }, "str"); - try testCase(struct { str: ?[]const u8 = null }, .{ .str = null }, "str="); - try testCase(struct { str: ?[]const u8 = null }, .{ .str = "foo" }, "str=foo"); - try testCase(struct { str: ?[]const u8 = "foo" }, .{ .str = "foo" }, "str=foo"); - try testCase(struct { str: ?[]const u8 = "foo" }, .{ .str = "foo" }, ""); - try testCase(struct { str: ?[]const u8 = "foo" }, .{ .str = null }, "str"); - try testCase(struct { str: ?[]const u8 = "foo" }, .{ .str = null }, "str="); + try testCase(false, struct { str: ?[]const u8 = null }, .{ .str = null }, ""); + try testCase(false, struct { str: ?[]const u8 = null }, .{ .str = null }, "str"); + try testCase(false, struct { str: ?[]const u8 = null }, .{ .str = null }, "str="); + try testCase(false, struct { str: ?[]const u8 = null }, .{ .str = "foo" }, "str=foo"); + try testCase(false, struct { str: ?[]const u8 = "foo" }, .{ .str = "foo" }, "str=foo"); + try testCase(false, struct { str: ?[]const u8 = "foo" }, .{ .str = "foo" }, ""); + try testCase(false, struct { str: ?[]const u8 = "foo" }, .{ .str = null }, "str"); + try testCase(false, struct { str: ?[]const u8 = "foo" }, .{ .str = null }, "str="); const rand_uuid = comptime util.Uuid.parse("c1fb6578-4d0c-4eb9-9f67-d56da3ae6f5d") catch unreachable; - try testCase(struct { id: ?util.Uuid = null }, .{ .id = null }, ""); - try testCase(struct { id: ?util.Uuid = null }, .{ .id = null }, "id="); - try testCase(struct { id: ?util.Uuid = null }, .{ .id = null }, "id"); - try testCase(struct { id: ?util.Uuid = null }, .{ .id = rand_uuid }, "id=" ++ rand_uuid.toCharArray()); - try testCase(struct { id: ?util.Uuid = rand_uuid }, .{ .id = rand_uuid }, ""); - try testCase(struct { id: ?util.Uuid = rand_uuid }, .{ .id = null }, "id="); - try testCase(struct { id: ?util.Uuid = rand_uuid }, .{ .id = null }, "id"); - try testCase(struct { id: ?util.Uuid = rand_uuid }, .{ .id = rand_uuid }, "id=" ++ rand_uuid.toCharArray()); + try testCase(false, struct { id: ?util.Uuid = null }, .{ .id = null }, ""); + try testCase(false, struct { id: ?util.Uuid = null }, .{ .id = null }, "id="); + try testCase(false, struct { id: ?util.Uuid = null }, .{ .id = null }, "id"); + try testCase(false, struct { id: ?util.Uuid = null }, .{ .id = rand_uuid }, "id=" ++ rand_uuid.toCharArray()); + try testCase(false, struct { id: ?util.Uuid = rand_uuid }, .{ .id = rand_uuid }, ""); + try testCase(false, struct { id: ?util.Uuid = rand_uuid }, .{ .id = null }, "id="); + try testCase(false, struct { id: ?util.Uuid = rand_uuid }, .{ .id = null }, "id"); + try testCase(false, struct { id: ?util.Uuid = rand_uuid }, .{ .id = rand_uuid }, "id=" ++ rand_uuid.toCharArray()); const SubStruct = struct { sub: struct { @@ -302,9 +302,9 @@ test "parse" { bar: usize = 2, } = .{}, }; - try testCase(SubStruct, .{ .sub = .{ .foo = 1, .bar = 2 } }, ""); - try testCase(SubStruct, .{ .sub = .{ .foo = 3, .bar = 3 } }, "sub.foo=3&sub.bar=3"); - try testCase(SubStruct, .{ .sub = .{ .foo = 3, .bar = 2 } }, "sub.foo=3"); + try testCase(false, SubStruct, .{ .sub = .{ .foo = 1, .bar = 2 } }, ""); + try testCase(false, SubStruct, .{ .sub = .{ .foo = 3, .bar = 3 } }, "sub.foo=3&sub.bar=3"); + try testCase(false, SubStruct, .{ .sub = .{ .foo = 3, .bar = 2 } }, "sub.foo=3"); // TODO: Semantics are ill-defined here. What happens if the substruct doesn't have // default values? @@ -313,8 +313,8 @@ test "parse" { // foo: usize = 1, // } = null, // }; - // try testCase(SubStruct2, .{ .sub = null }, ""); - // try testCase(SubStruct2, .{ .sub = null }, "sub="); + // try testCase(false, SubStruct2, .{ .sub = null }, ""); + // try testCase(false, SubStruct2, .{ .sub = null }, "sub="); // TODO: also here (semantics are well defined it just breaks tests) // const SubUnion = struct { @@ -323,8 +323,8 @@ test "parse" { // bar: usize, // } = null, // }; - // try testCase(SubUnion, .{ .sub = null }, ""); - // try testCase(SubUnion, .{ .sub = null }, "sub="); + // try testCase(false, SubUnion, .{ .sub = null }, ""); + // try testCase(false, SubUnion, .{ .sub = null }, "sub="); const SubUnion2 = struct { sub: ?struct { @@ -335,9 +335,9 @@ test "parse" { }, } = null, }; - try testCase(SubUnion2, .{ .sub = null }, ""); - try testCase(SubUnion2, .{ .sub = .{ .foo = 1, .val = .{ .bar = "abc" } } }, "sub.foo=1&sub.bar=abc"); - try testCase(SubUnion2, .{ .sub = .{ .foo = 1, .val = .{ .baz = "abc" } } }, "sub.foo=1&sub.baz=abc"); + try testCase(false, SubUnion2, .{ .sub = null }, ""); + try testCase(false, SubUnion2, .{ .sub = .{ .foo = 1, .val = .{ .bar = "abc" } } }, "sub.foo=1&sub.bar=abc"); + try testCase(false, SubUnion2, .{ .sub = .{ .foo = 1, .val = .{ .baz = "abc" } } }, "sub.foo=1&sub.baz=abc"); } test "encodeStruct" {