Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf8909740f | ||
|
|
a7b0714643 | ||
|
|
d539ee3b08 |
@@ -105,10 +105,7 @@ function buildApp({ configOk = true, servicesOk = true, dockerOk = true, caddyOk
|
||||
|
||||
try {
|
||||
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), 3000);
|
||||
const response = await fetch(`${caddyUrl}/config/`, { signal: controller.signal });
|
||||
clearTimeout(timeout);
|
||||
const response = await fetch(`${caddyUrl}/config/apps/http/servers/srv0/listen`, { signal: AbortSignal.timeout(10000) });
|
||||
checks.caddy = { ok: response.ok, status: response.status };
|
||||
if (!response.ok) allOk = false;
|
||||
} catch (e) {
|
||||
|
||||
@@ -109,10 +109,7 @@ function buildApp({ configOk = true, servicesOk = true, dockerOk = true } = {})
|
||||
}
|
||||
try {
|
||||
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), 3000);
|
||||
const response = await fetch(`${caddyUrl}/config/`, { signal: controller.signal });
|
||||
clearTimeout(timeout);
|
||||
const response = await fetch(`${caddyUrl}/config/apps/http/servers/srv0/listen`, { signal: AbortSignal.timeout(10000) });
|
||||
checks.caddy = { ok: response.ok, status: response.status };
|
||||
if (!response.ok) allOk = false;
|
||||
} catch (e) {
|
||||
|
||||
+24
-10
@@ -192,13 +192,27 @@ async function createApp() {
|
||||
// auto-login pages) historically call these endpoints under the pre-1.5.0
|
||||
// prefix `/api/auth/...`. The canonical mount is `/api/v1`. Hand-maintained
|
||||
// Caddyfiles have repeatedly drifted back to the old prefix and 404'd the SSO
|
||||
// gate (breaking Plex/Jellyfin/Emby/chat). Transparently rewrite ONLY these two
|
||||
// auth paths to the v1 mount so the gate is tolerant of that drift. Must run
|
||||
// before configureMiddleware() so CSRF/auth see the canonical path. This is
|
||||
// deliberately narrow — NOT a general `/api` -> `/api/v1` alias.
|
||||
// gate (breaking Plex/Jellyfin/Emby/chat). Transparently rewrite ONLY these
|
||||
// three auth paths to the v1 mount so the gate is tolerant of that drift.
|
||||
// Must run before configureMiddleware() so CSRF/auth see the canonical path.
|
||||
// This is deliberately narrow — NOT a general `/api` -> `/api/v1` alias.
|
||||
//
|
||||
// Path mapping (legacy -> canonical):
|
||||
// /api/auth/gate/<id> -> /api/v1/auth/gate/<id> (mounted at /auth/gate/:serviceId)
|
||||
// /api/auth/app-token/<id> -> /api/v1/auth/app-token/<id> (mounted at /auth/app-token/:serviceId)
|
||||
// /api/auth/totp/check-session -> /api/v1/totp/check-session (mounted at /totp/check-session — no /auth prefix)
|
||||
//
|
||||
// The totp case drops `/auth` because the canonical route is /totp/check-session
|
||||
// (no /auth prefix) but the legacy JS still uses /api/auth/totp/check-session.
|
||||
// Without this rewrite the JS gets a 404 and the page hangs at
|
||||
// "Signing in to Plex..." forever (user-reported 2026-07-09).
|
||||
app.use((req, res, next) => {
|
||||
if (req.url.startsWith('/api/auth/gate/') || req.url.startsWith('/api/auth/app-token/')) {
|
||||
req.url = '/api/v1' + req.url.slice(4); // '/api'.length === 4
|
||||
} else if (req.url.startsWith('/api/auth/totp/check-session')) {
|
||||
// Legacy: /api/auth/totp/check-session -> /api/v1/totp/check-session
|
||||
// Drop both '/api' and '/auth' prefixes (9 chars total).
|
||||
req.url = '/api/v1' + req.url.slice(9); // '/api/auth'.length === 9
|
||||
}
|
||||
next();
|
||||
});
|
||||
@@ -727,14 +741,14 @@ async function createApp() {
|
||||
}
|
||||
|
||||
// Check 4: Caddy admin API reachable
|
||||
// Use fetchT() (NOT native fetch) because undici fetch rejects Caddy admin
|
||||
// on :2019, and probe the LIGHTEST endpoint (srv0/listen = 9 bytes) to avoid
|
||||
// head-of-line blocking when /load or another config mutation is in flight.
|
||||
// A previous `/config/` probe hit the 3s AbortController timeout with
|
||||
// "This operation was aborted" while Caddy was actually healthy.
|
||||
try {
|
||||
const caddyUrl = config.CADDY_ADMIN_URL || 'http://localhost:2019';
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), 3000);
|
||||
const response = await fetch(`${caddyUrl}/config/`, {
|
||||
signal: controller.signal
|
||||
});
|
||||
clearTimeout(timeout);
|
||||
const response = await fetchT(`${caddyUrl}/config/apps/http/servers/srv0/listen`, {}, 10000);
|
||||
checks.caddy = { ok: response.ok, status: response.status };
|
||||
if (!response.ok) allOk = false;
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user