mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
fix(sidecar): block cloud fallback in Docker mode (#1726)
Self-hosted Docker instances must not proxy unhandled routes to api.worldmonitor.app. When LOCAL_API_MODE=docker, cloudFallback is forced to false regardless of LOCAL_API_CLOUD_FALLBACK env var. Logs a warning if the user explicitly requested fallback. Prevents self-hosted users from unknowingly sending traffic to the production Vercel deployment.
This commit is contained in:
@@ -530,7 +530,11 @@ function resolveConfig(options = {}) {
|
||||
].find((candidate) => existsSync(candidate)) ?? path.join(resourceDir, 'api');
|
||||
const dataDir = String(options.dataDir ?? process.env.LOCAL_API_DATA_DIR ?? resourceDir);
|
||||
const mode = String(options.mode ?? process.env.LOCAL_API_MODE ?? 'desktop-sidecar');
|
||||
const cloudFallback = String(options.cloudFallback ?? process.env.LOCAL_API_CLOUD_FALLBACK ?? '') === 'true';
|
||||
const requestedFallback = String(options.cloudFallback ?? process.env.LOCAL_API_CLOUD_FALLBACK ?? '') === 'true';
|
||||
const cloudFallback = mode === 'docker' ? false : requestedFallback;
|
||||
if (mode === 'docker' && requestedFallback) {
|
||||
(options.logger ?? console).warn('[local-api] Cloud fallback disabled in Docker mode (self-hosted instances must not proxy to api.worldmonitor.app)');
|
||||
}
|
||||
const logger = options.logger ?? console;
|
||||
|
||||
return {
|
||||
|
||||
@@ -528,6 +528,45 @@ test('strips browser origin headers when proxying to cloud fallback (cloudFallba
|
||||
}
|
||||
});
|
||||
|
||||
test('blocks cloud fallback in Docker mode even when explicitly requested', async () => {
|
||||
const remote = await setupRemoteServer();
|
||||
const localApi = await setupApiDir({
|
||||
'docker-test.js': `
|
||||
export default async function handler() {
|
||||
return new Response(JSON.stringify({ source: 'local-error' }), {
|
||||
status: 500,
|
||||
headers: { 'content-type': 'application/json' }
|
||||
});
|
||||
}
|
||||
`,
|
||||
});
|
||||
|
||||
const warnings = [];
|
||||
const app = await createLocalApiServer({
|
||||
port: 0,
|
||||
apiDir: localApi.apiDir,
|
||||
remoteBase: remote.remoteBase,
|
||||
cloudFallback: 'true',
|
||||
mode: 'docker',
|
||||
logger: { log() {}, warn(...args) { warnings.push(args.join(' ')); }, error() {} },
|
||||
});
|
||||
const { port } = await app.start();
|
||||
|
||||
try {
|
||||
const response = await fetch(`http://127.0.0.1:${port}/api/docker-test`);
|
||||
// Should NOT fall back to cloud; should return the local 500 directly
|
||||
assert.equal(response.status, 500);
|
||||
const body = await response.json();
|
||||
assert.equal(body.source, 'local-error');
|
||||
// Should have logged a warning about Docker mode blocking fallback
|
||||
assert.ok(warnings.some(w => w.includes('Docker mode')), 'Should warn about Docker mode blocking fallback');
|
||||
} finally {
|
||||
await app.close();
|
||||
await localApi.cleanup();
|
||||
await remote.close();
|
||||
}
|
||||
});
|
||||
|
||||
test('responds to OPTIONS preflight with CORS headers', async () => {
|
||||
const localApi = await setupApiDir({
|
||||
'data.js': `
|
||||
|
||||
Reference in New Issue
Block a user