diff --git a/src/main/controllers.zig b/src/main/controllers.zig index ede27c3..d965a07 100644 --- a/src/main/controllers.zig +++ b/src/main/controllers.zig @@ -7,16 +7,10 @@ const util = @import("util"); const query_utils = @import("./query.zig"); const json_utils = @import("./json.zig"); -pub const auth = @import("./controllers/api/auth.zig"); -pub const communities = @import("./controllers/api/communities.zig"); -pub const invites = @import("./controllers/api/invites.zig"); -pub const users = @import("./controllers/api/users.zig"); -pub const follows = @import("./controllers/api/users/follows.zig"); -pub const notes = @import("./controllers/api/notes.zig"); -pub const streaming = @import("./controllers/api/streaming.zig"); -pub const timelines = @import("./controllers/api/timelines.zig"); +const web_controllers = @import("./controllers/web.zig"); +const api_controllers = @import("./controllers/api.zig"); -const web = @import("./controllers/web.zig"); +const routes = api_controllers ++ web_controllers.routes; const mdw = http.middleware; @@ -40,47 +34,44 @@ const not_found = struct { const base_handler = mdw.SplitUri(mdw.CatchErrors(not_found, mdw.DefaultErrorHandler)); -fn InjectApiConn(comptime ApiSource: type) type { - return struct { - api_source: ApiSource, - fn getApiConn(self: @This(), alloc: std.mem.Allocator, req: anytype) !ApiSource.Conn { - const host = req.headers.get("Host") orelse return error.NoHost; - const auth_header = req.headers.get("Authorization"); - const token = if (auth_header) |header| blk: { - const prefix = "bearer "; - if (header.len < prefix.len) break :blk null; - if (!std.ascii.eqlIgnoreCase(prefix, header[0..prefix.len])) break :blk null; - break :blk header[prefix.len..]; - } else null; +const inject_api_conn = struct { + fn getApiConn(alloc: std.mem.Allocator, api_source: anytype, req: anytype) !@TypeOf(api_source).Conn { + const host = req.headers.get("Host") orelse return error.NoHost; + const auth_header = req.headers.get("Authorization"); + const token = if (auth_header) |header| blk: { + const prefix = "bearer "; + if (header.len < prefix.len) break :blk null; + if (!std.ascii.eqlIgnoreCase(prefix, header[0..prefix.len])) break :blk null; + break :blk header[prefix.len..]; + } else null; - if (token) |t| return try self.api_source.connectToken(host, t, alloc); + if (token) |t| return try api_source.connectToken(host, t, alloc); - if (req.headers.getCookie("active_account") catch return error.BadRequest) |account| { - if (account.len + ("token.").len <= 64) { - var buf: [64]u8 = undefined; - const cookie_name = std.fmt.bufPrint(&buf, "token.{s}", .{account}) catch unreachable; - if (try req.headers.getCookie(cookie_name)) |token_hdr| { - return try self.api_source.connectToken(host, token_hdr, alloc); - } - } else return error.InvalidCookie; - } - - return try self.api_source.connectUnauthorized(host, alloc); + if (req.headers.getCookie("active_account") catch return error.BadRequest) |account| { + if (account.len + ("token.").len <= 64) { + var buf: [64]u8 = undefined; + const cookie_name = std.fmt.bufPrint(&buf, "token.{s}", .{account}) catch unreachable; + if (try req.headers.getCookie(cookie_name)) |token_hdr| { + return try api_source.connectToken(host, token_hdr, alloc); + } + } else return error.InvalidCookie; } - fn handle(self: @This(), req: anytype, res: anytype, ctx: anytype, next: anytype) !void { - var api_conn = try self.getApiConn(ctx.allocator, req); - defer api_conn.close(); + return try api_source.connectUnauthorized(host, alloc); + } - return next.handle( - req, - res, - mdw.injectContext(.{ .api_conn = &api_conn }), - {}, - ); - } - }; -} + pub fn handle(_: @This(), req: anytype, res: anytype, ctx: anytype, next: anytype) !void { + var api_conn = try getApiConn(ctx.allocator, ctx.api_source, req); + defer api_conn.close(); + + return next.handle( + req, + res, + mdw.injectContext(.{ .api_conn = &api_conn }), + {}, + ); + } +}; pub fn EndpointRequest(comptime Endpoint: type) type { return struct { @@ -140,7 +131,6 @@ fn CallApiEndpoint(comptime Endpoint: type) type { pub fn apiEndpoint( comptime Endpoint: type, - api_source: anytype, ) return_type: { const RequestType = EndpointRequest(Endpoint); break :return_type mdw.Apply(std.meta.Tuple(.{ @@ -149,7 +139,7 @@ pub fn apiEndpoint( @TypeOf(RequestType.query_middleware), @TypeOf(RequestType.body_middleware), // TODO: allocation strategy - InjectApiConn(@TypeOf(api_source)), + @TypeOf(inject_api_conn), CallApiEndpoint(Endpoint), })); } { @@ -160,7 +150,7 @@ pub fn apiEndpoint( RequestType.query_middleware, RequestType.body_middleware, // TODO: allocation strategy - InjectApiConn(@TypeOf(api_source)){ .api_source = api_source }, + inject_api_conn, CallApiEndpoint(Endpoint){}, }); } @@ -177,25 +167,6 @@ pub fn routeRequest(api_source: anytype, req: *http.Request, res: *http.Response //if (!found) response.status(.not_found) catch {}; } -const routes = .{ - auth.login, - auth.verify_login, - communities.create, - communities.query, - invites.create, - users.create, - notes.create, - notes.get, - streaming.streaming, - timelines.global, - timelines.local, - timelines.home, - follows.create, - follows.delete, - follows.query_followers, - follows.query_following, -} ++ web.routes; - pub const AllocationStrategy = enum { arena, normal, diff --git a/src/main/controllers/api.zig b/src/main/controllers/api.zig new file mode 100644 index 0000000..38de71e --- /dev/null +++ b/src/main/controllers/api.zig @@ -0,0 +1,29 @@ +const controllers = @import("../controllers.zig"); + +const auth = @import("./api/auth.zig"); +const communities = @import("./api/communities.zig"); +const invites = @import("./api/invites.zig"); +const users = @import("./api/users.zig"); +const follows = @import("./api/users/follows.zig"); +const notes = @import("./api/notes.zig"); +const streaming = @import("./api/streaming.zig"); +const timelines = @import("./api/timelines.zig"); + +pub const routes = .{ + controllers.apiEndpoint(auth.login), + controllers.apiEndpoint(auth.verify_login), + controllers.apiEndpoint(communities.create), + controllers.apiEndpoint(communities.query), + controllers.apiEndpoint(invites.create), + controllers.apiEndpoint(users.create), + controllers.apiEndpoint(notes.create), + controllers.apiEndpoint(notes.get), + controllers.apiEndpoint(streaming.streaming), + controllers.apiEndpoint(timelines.global), + controllers.apiEndpoint(timelines.local), + controllers.apiEndpoint(timelines.home), + controllers.apiEndpoint(follows.create), + controllers.apiEndpoint(follows.delete), + controllers.apiEndpoint(follows.query_followers), + controllers.apiEndpoint(follows.query_following), +}; diff --git a/src/main/controllers/web.zig b/src/main/controllers/web.zig index 9ee8ac4..430e405 100644 --- a/src/main/controllers/web.zig +++ b/src/main/controllers/web.zig @@ -1,11 +1,12 @@ const std = @import("std"); +const controllers = @import("../controllers.zig"); pub const routes = .{ - index, - about, - login, - global_timeline, - cluster.overview, + controllers.apiEndpoint(index), + controllers.apiEndpoint(about), + controllers.apiEndpoint(login), + controllers.apiEndpoint(global_timeline), + controllers.apiEndpoint(cluster.overview), }; const index = struct {