diff --git a/src/http/middleware.zig b/src/http/middleware.zig index 190a60d..fb3095a 100644 --- a/src/http/middleware.zig +++ b/src/http/middleware.zig @@ -634,7 +634,7 @@ const BaseContentType = enum { other, }; -pub fn parseBodyFromReader( +fn parseBodyFromRequest( comptime T: type, comptime options: ParseBodyOptions, content_type: ?[]const u8, @@ -703,7 +703,7 @@ pub fn ParseBody(comptime Body: type, comptime options: ParseBodyOptions) type { } var stream = req.body orelse return error.NoBody; - const body = try parseBodyFromReader(Body, options, content_type, stream.reader(), ctx.allocator); + const body = try parseBodyFromRequest(Body, options, content_type, stream.reader(), ctx.allocator); defer util.deepFree(ctx.allocator, body); return next.handle( @@ -719,11 +719,11 @@ pub fn parseBody(comptime Body: type) ParseBody(Body) { return .{}; } -test "parseBodyFromReader" { +test "parseBodyFromRequest" { const testCase = struct { fn case(content_type: []const u8, body: []const u8, expected: anytype) !void { var stream = std.io.StreamSource{ .const_buffer = std.io.fixedBufferStream(body) }; - const result = try parseBodyFromReader(@TypeOf(expected), .{}, content_type, stream.reader(), std.testing.allocator); + const result = try parseBodyFromRequest(@TypeOf(expected), .{}, content_type, stream.reader(), std.testing.allocator); defer util.deepFree(std.testing.allocator, result); try util.testing.expectDeepEqual(expected, result); diff --git a/src/main/controllers.zig b/src/main/controllers.zig index ad971b5..ae62126 100644 --- a/src/main/controllers.zig +++ b/src/main/controllers.zig @@ -80,11 +80,6 @@ pub fn EndpointRequest(comptime Endpoint: type) type { false, }; - const union_tag_from_query_param = if (@hasDecl(Endpoint, "body_tag_from_query_param")) blk: { - if (!std.meta.trait.is(.Union)(Body)) @compileError("body_tag_from_query_param only valid if body is a union"); - break :blk @as(?[]const u8, Endpoint.body_tag_from_query_param); - } else null; - allocator: std.mem.Allocator, method: http.Method, @@ -102,9 +97,9 @@ pub fn EndpointRequest(comptime Endpoint: type) type { //else mdw.ParsePathArgs(Endpoint.path, Args){}; - const body_middleware = if (union_tag_from_query_param) |param| - ParseBodyWithQueryType(Body, param, body_options){} - else + const body_middleware = //if (Body == void) + //mdw.injectContext(.{ .body = {} }) + //else mdw.ParseBody(Body, body_options){}; const query_middleware = //if (Query == void) @@ -114,56 +109,6 @@ pub fn EndpointRequest(comptime Endpoint: type) type { }; } -/// Gets a tag from the query param with the given name, then treats the request body -/// as the respective union type -fn ParseBodyWithQueryType(comptime Union: type, comptime query_param_name: []const u8, comptime options: anytype) type { - return struct { - pub fn handle(_: @This(), req: anytype, res: anytype, ctx: anytype, next: anytype) !void { - const Tag = std.meta.Tag(Union); - const Param = @Type(.{ .Struct = .{ - .fields = &.{.{ - .name = query_param_name, - .field_type = Tag, - .default_value = null, - .is_comptime = false, - .alignment = if (@sizeOf(Tag) == 0) 0 else @alignOf(Tag), - }}, - .decls = &.{}, - .layout = .Auto, - .is_tuple = false, - } }); - const param = try http.urlencode.parse(ctx.allocator, true, Param, ctx.query_string); - - var result: ?Union = null; - const content_type = req.headers.get("Content-Type"); - inline for (comptime std.meta.tags(Tag)) |tag| { - if (@field(param, query_param_name) == tag) { - std.debug.assert(result == null); - const P = std.meta.TagPayload(Union, tag); - - std.log.debug("Deserializing to type {}", .{P}); - - var stream = req.body orelse return error.NoBody; - result = @unionInit(Union, @tagName(tag), try mdw.parseBodyFromReader( - P, - options, - content_type, - stream.reader(), - ctx.allocator, - )); - } - } - - return mdw.injectContextValue("body", result.?).handle( - req, - res, - ctx, - next, - ); - } - }; -} - fn CallApiEndpoint(comptime Endpoint: type) type { return struct { pub fn handle(_: @This(), req: anytype, res: anytype, ctx: anytype, _: void) !void { diff --git a/src/main/controllers/web.zig b/src/main/controllers/web.zig index 5ec6d55..835e64e 100644 --- a/src/main/controllers/web.zig +++ b/src/main/controllers/web.zig @@ -279,39 +279,27 @@ const drive = struct { }; const Action = enum { - mkdir, - delete, + mkcol, }; - pub const body_tag_from_query_param = "action"; - pub const Body = union(Action) { - mkdir: struct { - name: []const u8, + pub const Body = struct { + action: Action, + data: union(Action) { + mkcol: struct { + name: []const u8, + }, }, - delete: struct {}, }; pub fn handler(req: anytype, res: anytype, srv: anytype) !void { - switch (req.body) { - .mkdir => |body| { - _ = try srv.driveMkdir(req.args.path, body.name); + if (req.body.action != req.body.data) return error.BadRequest; + switch (req.body.data) { + .mkcol => |data| { + _ = try srv.driveMkdir(req.args.path, data.name); // TODO try servePage(req, res, srv); }, - .delete => { - const trimmed_path = std.mem.trim(u8, req.args.path, "/"); - _ = try srv.driveDelete(trimmed_path); - - const dir = trimmed_path[0 .. std.mem.lastIndexOfScalar(u8, trimmed_path, '/') orelse trimmed_path.len]; - const url = try std.fmt.allocPrint(srv.allocator, "{s}/drive/{s}", .{ - req.mount_path, - dir, - }); - defer srv.allocator.free(url); - try res.headers.put("Location", url); - return res.status(.see_other); - }, } } }; diff --git a/src/main/controllers/web/drive/directory.tmpl.html b/src/main/controllers/web/drive/directory.tmpl.html index 39f4b2d..5135b6a 100644 --- a/src/main/controllers/web/drive/directory.tmpl.html +++ b/src/main/controllers/web/drive/directory.tmpl.html @@ -29,11 +29,12 @@ - @@ -48,25 +49,6 @@ {$dir.name.?} - - - - - - {#case file |$file|} {#if %user |$u|} @@ -90,23 +72,6 @@ {#if $file.meta.content_type |$t|}{$t}{/if} {$file.meta.size} {$file.meta.created_at} - - - {/switch =} {/for=} diff --git a/src/util/serialize.zig b/src/util/serialize.zig index 120ca48..a7ca8e1 100644 --- a/src/util/serialize.zig +++ b/src/util/serialize.zig @@ -266,11 +266,7 @@ pub fn DeserializerContext(comptime Result: type, comptime From: type, comptime } pub fn finish(self: *@This(), allocator: std.mem.Allocator) !Result { - return (try self.deserialize(allocator, Result, self.data, &.{})) orelse - if (std.meta.fields(Result).len == 0) - return .{} - else - return error.MissingField; + return (try self.deserialize(allocator, Result, self.data, &.{})) orelse error.MissingField; } fn getSerializedField(self: *@This(), comptime field_ref: FieldRef) ?From {