Files
stack/scripts/e2e-orgs-proxy.mjs
T

50 lines
3.7 KiB
JavaScript

// Loopback-only synthetic proxy for the organizations integration E2E.
import http from 'node:http';
import fs from 'node:fs';
import { createHash } from 'node:crypto';
const [area, portArg = '0'] = process.argv.slice(2);
const forbidden = new Set([7332, 7340, 7341, 33223, 17450, 17443, 44307, 8317]);
const file = `${area}/proxy-keys.json`, delay = `${area}/delay-put`;
let keys = fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, 'utf8')) : ['fixture-foreign'];
const server = http.createServer(async (req, res) => {
const reply = (status, data) => { res.writeHead(status, {'content-type':'application/json'}); res.end(JSON.stringify(data)); };
if (req.url === '/test/alpha-key') {
const alpha = keys.filter(k => /-alpha-key-/.test(k));
if (alpha.length !== 1) return reply(409, { error: 'alpha key missing' });
const key = alpha[0];
const probe = await fetch(`http://127.0.0.1:${server.address().port}/v1/models`, { headers: { authorization: `Bearer ${key}` } });
return reply(200, { keyId: createHash('sha256').update(key).digest('hex').slice(0,12), accepted: probe.ok, alphaKeys: alpha.length,
betaSentinels: keys.filter(k => /-beta-sentinel-/.test(k)).length, gammaSentinels: keys.filter(k => /-gamma-sentinel-/.test(k)).length });
}
if (req.url === '/v1/models') return reply(keys.includes(req.headers.authorization?.slice(7)) ? 200 : 401, {});
if (req.url === '/v8/management/config/access/api-keys') {
if (req.headers.authorization !== 'Bearer fixture-management') return reply(401, {});
if (req.method === 'GET') return reply(200, keys);
if (req.method !== 'PUT') return reply(405, {});
const chunks = []; for await (const c of req) chunks.push(c);
const next = JSON.parse(Buffer.concat(chunks));
if (fs.existsSync(delay)) await new Promise(resolve => setTimeout(resolve, 12000));
keys = next; fs.writeFileSync(file, JSON.stringify(keys), {mode:0o600}); return reply(200, {status:'ok'});
}
if (req.method === 'POST' && /^\/v1\/messages(?:\?|$)/.test(req.url ?? '')) {
if (!keys.includes(req.headers['x-api-key'])) return reply(401, {});
const chunks = []; for await (const c of req) chunks.push(c);
const body = JSON.parse(Buffer.concat(chunks));
const msg = {id:'msg_proxy_fixture',type:'message',role:'assistant',model:body.model,stop_sequence:null};
if (!body.stream) return reply(200, {...msg,content:[{type:'text',text:'PINEAPPLE'}],stop_reason:'end_turn',usage:{input_tokens:1,output_tokens:1}});
res.writeHead(200, {'content-type':'text/event-stream','cache-control':'no-cache'});
const event = (type,data) => res.write(`event: ${type}\ndata: ${JSON.stringify({type,...data})}\n\n`);
event('message_start',{message:{...msg,content:[],stop_reason:null,usage:{input_tokens:1,output_tokens:0}}});
event('content_block_start',{index:0,content_block:{type:'text',text:''}});
event('content_block_delta',{index:0,delta:{type:'text_delta',text:'PINEAPPLE'}});
event('content_block_stop',{index:0}); event('message_delta',{delta:{stop_reason:'end_turn',stop_sequence:null},usage:{output_tokens:1}}); event('message_stop',{}); return res.end();
}
return reply(404, {});
});
async function listen(port) { await new Promise((resolve,reject)=>{ server.once('error',reject); server.listen(port,'127.0.0.1',resolve); }); }
let port = Number(portArg);
for (;;) { await listen(port); port = server.address().port; if (!forbidden.has(port)) break; await new Promise(r => server.close(r)); if (portArg !== '0') throw Error('forbidden port'); port = 0; }
fs.writeFileSync(`${area}/proxy-ready.json`, JSON.stringify({port,pid:process.pid}), {mode:0o600});
const stop = () => { server.closeAllConnections(); server.close(() => process.exit(0)); };
process.on('SIGTERM',stop); process.on('SIGINT',stop);