╭ changed ──╮ │src/web.zig│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │142 const uri = try std.Uri.parseAfterScheme("", request.head.target); │ │143 const path = uri.path.percent_encoded; │ │144 │ │145 - // login/logout are page-scoped. the base (the path minus the trailing verb) │ │146 - // is where we redirect afterward, so logging in keeps you on the page you │ │147 - // were on instead of jumping to the home view. │ │148 - if (method == .POST and std.mem.endsWith(u8, path, "/login")) { │ │149 - return handleLogin(io, request, allocator, path[0 .. path.len - "/login".len], admin_repo_path, session_store);│ │145 + // POST routes can be scoped by any page, so they can redirect using │ │146 + // the base of the URL. this allows logging in to keep you on the page │ │147 + // you were on. │ │148 + if (method == .POST) { │ │149 + const PostRoute = enum { login, logout, ansi }; │ │150 + inline for (@typeInfo(PostRoute).@"enum".fields) |field| { │ │151 + const suffix = "/" ++ field.name; │ │152 + if (std.mem.endsWith(u8, path, suffix)) { │ │153 + const base = path[0 .. path.len - suffix.len]; │ │154 + return switch (@field(PostRoute, field.name)) { │ │155 + .login => handleLogin(io, request, allocator, base, admin_repo_path, session_store), │ │156 + .logout => handleLogout(request, base, session_store), │ │157 + .ansi => handleAnsi(io, request, allocator, base, admin_repo_path, session_store), │ │158 + }; │ │159 + } │ │160 + } │ │161 } │ │151 - if (method == .POST and std.mem.endsWith(u8, path, "/logout")) { │ │152 - return handleLogout(request, path[0 .. path.len - "/logout".len], session_store); │ │153 - } │ │154 - if (method == .POST and std.mem.endsWith(u8, path, "/ansi")) { │ │155 - return handleAnsi(io, request, allocator, path[0 .. path.len - "/ansi".len], admin_repo_path, session_store); │ │156 - } │ │162 │ │163 const get_or_head = method == .GET or method == .HEAD; │ │164 if (!get_or_head) { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯