diff --git a/src/http/headers.zig b/src/http/headers.zig index 8b8100b..1b91865 100644 --- a/src/http/headers.zig +++ b/src/http/headers.zig @@ -133,6 +133,7 @@ pub const Fields = struct { } = null, }; + // TODO: Escape cookie values pub fn setCookie(self: *Fields, name: []const u8, value: []const u8, opt: CookieOptions) !void { const cookie = try std.fmt.allocPrint( self.allocator, @@ -151,4 +152,20 @@ pub const Fields = struct { // TODO: reduce unnecessary allocations try self.append("Set-Cookie", cookie); } + + // TODO: perform validation at request parse time? + pub fn getCookie(self: *Fields, name: []const u8) !?[]const u8 { + const hdr = self.get("Cookie") orelse return null; + var iter = std.mem.split(u8, hdr, ";"); + while (iter.next()) |cookie| { + const trimmed = std.mem.trimLeft(u8, cookie, " "); + const cookie_name = std.mem.sliceTo(trimmed, '='); + if (std.mem.eql(u8, name, cookie_name)) { + const rest = trimmed[cookie_name.len..]; + if (rest.len == 0) return error.InvalidCookie; + return rest[1..]; + } + } + return null; + } }; diff --git a/src/main/controllers.zig b/src/main/controllers.zig index 821ebd0..eeba618 100644 --- a/src/main/controllers.zig +++ b/src/main/controllers.zig @@ -198,6 +198,16 @@ pub fn Context(comptime Route: type) type { if (token) |t| break :conn 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| { + break :conn try api_source.connectToken(host, token_hdr, alloc); + } + } else return error.InvalidToken; + } + break :conn try api_source.connectUnauthorized(host, alloc); }; defer api_conn.close();