fix(auth): restore /echo prefix after proxy strips it from next param

The reverse proxy strips /echo/ before Python, so next=/workspace.html.
Both the JS redirect and the server-side already-logged-in path now
prepend /echo to produce a valid public URL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-29 14:11:22 +00:00
parent 38259f3cfd
commit 77df09974c
2 changed files with 17 additions and 6 deletions

View File

@@ -10,7 +10,7 @@ import os
import sys
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from urllib.parse import quote as _urlquote
from urllib.parse import quote as _urlquote, parse_qs, urlparse
# Make dashboard/ importable for the handler submodules (constants,
# habits_helpers, handlers.*). Tests rely on this as well.
@@ -243,11 +243,19 @@ class TaskBoardHandler(
return
elif self.path in ('/echo/login', '/login') or \
self.path.startswith(('/echo/login?', '/login?')):
# If already logged in, redirect to workspace; otherwise serve
# login.html (created in Lane B2).
# If already logged in, redirect to next (or workspace); otherwise serve login.html.
if self._check_dashboard_cookie():
qs = parse_qs(urlparse(self.path).query)
next_vals = qs.get('next', [])
nxt = next_vals[0] if next_vals else ''
# Proxy strips /echo/ before Python, so nxt is e.g. /workspace.html.
# Re-add the prefix so the browser lands on the right public URL.
if nxt and nxt.startswith('/') and '://' not in nxt:
dest = '/echo' + nxt
else:
dest = '/echo/workspace.html'
self.send_response(302)
self.send_header('Location', '/echo/workspace.html')
self.send_header('Location', dest)
self.send_header('Content-Length', '0')
self.end_headers()
return