release(v1.7.13-alpha): proxy app catalog server-side (CORS + CSP fix)
The Discover / Marketplace page fetched the app catalog directly from git.tx1138.com/lfg2025/app-catalog/raw/.../catalog.json in the browser. Two blockers hit the fleet simultaneously: (1) tx1138's Gitea doesn't emit Access-Control-Allow-Origin so the HTTPS fetch got CORS-blocked; (2) the HTTP IP-port fallback (http://23.182.128.160:3000/...) falls outside the node's `connect-src` CSP. Users saw the hardcoded fallback instead of the live catalog. Backend: new authenticated GET /api/app-catalog handler uses reqwest to pull catalog.json server-side (15s timeout) and returns it with application/json + 1h Cache-Control. Tries the HTTPS URL first, HTTP IP-port second. Frontend: curatedApps.ts now calls /api/app-catalog (same-origin, no CORS/CSP) with credentials included so the session cookie authenticates the proxy. Baked /catalog.json stays as the last resort. Artefacts: archipelago 0aaf7262…b979f22c 40371192 archipelago-frontend-1.7.13-alpha.tar.gz 27505811…efc6f4142 76982505 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,13 +22,13 @@ let cachedCatalog: AppCatalog | null = null
|
||||
let catalogFetchedAt = 0
|
||||
const CATALOG_TTL = 60 * 60 * 1000 // 1 hour cache
|
||||
|
||||
/** Remote catalog URLs — tried in order. First success wins. */
|
||||
/** Catalog URLs tried in order. First success wins.
|
||||
* Primary is the backend proxy (`/api/app-catalog`) — server-side fetch
|
||||
* bypasses CORS on git.tx1138.com and CSP restrictions on the IP-port
|
||||
* fallback. If the backend is offline (mid-restart etc.) we fall back
|
||||
* to the static copy baked into the frontend build. */
|
||||
const CATALOG_URLS = [
|
||||
// Primary: git.tx1138.com raw file (HTTPS, dynamic, updated without frontend rebuild)
|
||||
'https://git.tx1138.com/lfg2025/app-catalog/raw/branch/main/catalog.json',
|
||||
// Fallback: direct IP (HTTP, only works if CSP allows http://$host:*)
|
||||
'http://23.182.128.160:3000/lfg2025/app-catalog/raw/branch/main/catalog.json',
|
||||
// Last resort: local static file (baked into frontend build)
|
||||
'/api/app-catalog',
|
||||
'/catalog.json',
|
||||
]
|
||||
|
||||
@@ -40,7 +40,7 @@ export async function fetchAppCatalog(): Promise<AppCatalog | null> {
|
||||
|
||||
for (const url of CATALOG_URLS) {
|
||||
try {
|
||||
const res = await fetch(url, { signal: AbortSignal.timeout(5000) })
|
||||
const res = await fetch(url, { credentials: 'include', signal: AbortSignal.timeout(20000) })
|
||||
if (!res.ok) continue
|
||||
const data = await res.json() as AppCatalog
|
||||
if (!data.apps?.length) continue
|
||||
|
||||
Reference in New Issue
Block a user