Files
openchamber/packages/web/server/opencode-proxy.test.js
T
Bohdan Triapitsyn 2e5b02e753 test: cover external OpenCode proxy routing
- Expose external OpenCode base URL to proxy runtime
- Add regression coverage for provider requests through external OpenCode hosts
2026-04-07 22:48:17 +03:00

119 lines
3.8 KiB
JavaScript

import { afterEach, describe, expect, it } from 'bun:test';
import express from 'express';
import path from 'path';
import { registerOpenCodeProxy } from './lib/opencode/proxy.js';
const listen = (app, host = '127.0.0.1') => new Promise((resolve, reject) => {
const server = app.listen(0, host, () => resolve(server));
server.once('error', reject);
});
const closeServer = (server) => new Promise((resolve, reject) => {
if (!server) {
resolve();
return;
}
server.close((error) => {
if (error) {
reject(error);
return;
}
resolve();
});
});
describe('OpenCode proxy SSE forwarding', () => {
let upstreamServer;
let proxyServer;
afterEach(async () => {
await closeServer(proxyServer);
await closeServer(upstreamServer);
proxyServer = undefined;
upstreamServer = undefined;
});
it('forwards event streams with nginx-safe headers', async () => {
let seenAuthorization = null;
const upstream = express();
upstream.get('/global/event', (req, res) => {
seenAuthorization = req.headers.authorization ?? null;
res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
res.setHeader('Cache-Control', 'private, max-age=0');
res.setHeader('X-Upstream-Test', 'ok');
res.write('data: {"ok":true}\n\n');
res.end();
});
upstreamServer = await listen(upstream);
const upstreamPort = upstreamServer.address().port;
const app = express();
registerOpenCodeProxy(app, {
fs: {},
os: {},
path,
OPEN_CODE_READY_GRACE_MS: 0,
getRuntime: () => ({
openCodePort: upstreamPort,
isOpenCodeReady: true,
openCodeNotReadySince: 0,
isRestartingOpenCode: false,
}),
getOpenCodeAuthHeaders: () => ({ Authorization: 'Bearer test-token' }),
buildOpenCodeUrl: (requestPath) => `http://127.0.0.1:${upstreamPort}${requestPath}`,
ensureOpenCodeApiPrefix: () => {},
});
proxyServer = await listen(app);
const proxyPort = proxyServer.address().port;
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/global/event`, {
headers: { Accept: 'text/event-stream' },
});
expect(response.status).toBe(200);
expect(response.headers.get('content-type')).toContain('text/event-stream');
expect(response.headers.get('cache-control')).toBe('no-cache');
expect(response.headers.get('x-accel-buffering')).toBe('no');
expect(response.headers.get('x-upstream-test')).toBe('ok');
expect(await response.text()).toBe('data: {"ok":true}\n\n');
expect(seenAuthorization).toBe('Bearer test-token');
});
it('routes generic API requests through external OpenCode base URL', async () => {
const upstream = express();
upstream.get('/config/providers', (_req, res) => {
res.json({ ok: true, source: 'external-host' });
});
upstreamServer = await listen(upstream);
const upstreamPort = upstreamServer.address().port;
const externalBaseUrl = `http://127.0.0.1:${upstreamPort}`;
const app = express();
registerOpenCodeProxy(app, {
fs: {},
os: {},
path,
OPEN_CODE_READY_GRACE_MS: 0,
getRuntime: () => ({
openCodePort: 3902,
openCodeBaseUrl: externalBaseUrl,
isOpenCodeReady: true,
openCodeNotReadySince: 0,
isRestartingOpenCode: false,
}),
getOpenCodeAuthHeaders: () => ({}),
buildOpenCodeUrl: (requestPath) => `${externalBaseUrl}${requestPath}`,
ensureOpenCodeApiPrefix: () => {},
});
proxyServer = await listen(app);
const proxyPort = proxyServer.address().port;
const response = await fetch(`http://127.0.0.1:${proxyPort}/api/config/providers`);
expect(response.status).toBe(200);
expect(await response.json()).toEqual({ ok: true, source: 'external-host' });
});
});