#!/usr/bin/env node const DEFAULT_BASE_URL = `http://127.0.0.1:${process.env.PORT || "3001"}`; const BASE_URL = stripTrailingSlash( process.env.SMOKE_BASE_URL || process.argv[2] || DEFAULT_BASE_URL ); const REQUEST_TIMEOUT_MS = Number(process.env.SMOKE_TIMEOUT_MS || 20_000); const checks = [ { path: "/", method: "HEAD", expect: { status: [200] }, }, { path: "/classic", method: "HEAD", expect: { status: [307, 308], location: "/" }, }, { path: "/chat/test-id", method: "HEAD", expect: { status: [307, 308], location: "/" }, }, { path: "/settings", method: "HEAD", expect: { status: [307, 308], location: "/login?callbackUrl=%2Fsettings", }, }, ]; let hasFailure = false; for (const check of checks) { const result = await runCheck(check); if (!result.ok) { hasFailure = true; console.error(`FAIL ${check.method} ${check.path} - ${result.message}`); continue; } console.log(`PASS ${check.method} ${check.path} - ${result.message}`); } if (hasFailure) { process.exit(1); } async function runCheck(check) { const startedAt = Date.now(); const url = `${BASE_URL}${check.path}`; try { const response = await fetch(url, { method: check.method, redirect: "manual", headers: { "user-agent": "Codex Route Smoke Check", }, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), }); const durationMs = Date.now() - startedAt; const location = response.headers.get("location"); if (!check.expect.status.includes(response.status)) { return { ok: false, message: `expected status ${check.expect.status.join( "/" )}, got ${response.status} in ${durationMs}ms`, }; } if ( check.expect.location && !matchesLocation(location, check.expect.location) ) { return { ok: false, message: `expected location ${check.expect.location}, got ${ location || "" } in ${durationMs}ms`, }; } const redirectMessage = check.expect.location ? `, location ${check.expect.location}` : ""; return { ok: true, message: `status ${response.status}${redirectMessage} in ${durationMs}ms`, }; } catch (error) { return { ok: false, message: error instanceof Error ? error.message : String(error), }; } } function matchesLocation(actual, expected) { if (!actual) { return false; } if (actual === expected) { return true; } try { const actualUrl = new URL(actual, BASE_URL); return `${actualUrl.pathname}${actualUrl.search}` === expected; } catch { return false; } } function stripTrailingSlash(value) { return value.endsWith("/") ? value.slice(0, -1) : value; }