mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-05 10:18:47 +00:00
fix(codex): cap buffered upstream error response size (#1375)
This commit is contained in:
@@ -296,6 +296,39 @@ describe('CodexReasoningProxy extended-context compatibility', () => {
|
|||||||
expect((capturedBody?.reasoning as JsonRecord | undefined)?.effort).toBeUndefined();
|
expect((capturedBody?.reasoning as JsonRecord | undefined)?.effort).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('rejects oversized non-2xx upstream error bodies', async () => {
|
||||||
|
const upstream = http.createServer((_req, res) => {
|
||||||
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
||||||
|
const chunk = 'x'.repeat(1024 * 1024);
|
||||||
|
for (let i = 0; i < 11; i += 1) {
|
||||||
|
res.write(chunk);
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
cleanupServers.push(upstream);
|
||||||
|
|
||||||
|
const upstreamPort = await listenOnRandomPort(upstream);
|
||||||
|
const proxy = new CodexReasoningProxy({
|
||||||
|
upstreamBaseUrl: `http://127.0.0.1:${upstreamPort}`,
|
||||||
|
modelMap: { defaultModel: 'gpt-5.4' },
|
||||||
|
defaultEffort: 'medium',
|
||||||
|
});
|
||||||
|
|
||||||
|
const proxyPort = await proxy.start();
|
||||||
|
const response = await postJson(
|
||||||
|
`http://127.0.0.1:${proxyPort}/api/provider/codex/v1/messages`,
|
||||||
|
{
|
||||||
|
model: 'gpt-5.4',
|
||||||
|
messages: [],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
proxy.stop();
|
||||||
|
|
||||||
|
expect(response.statusCode).toBe(502);
|
||||||
|
expect(response.body.error).toContain('Upstream error response exceeded 10MB limit');
|
||||||
|
});
|
||||||
|
|
||||||
it('keeps fast service tier when disableEffort is enabled', async () => {
|
it('keeps fast service tier when disableEffort is enabled', async () => {
|
||||||
let capturedBody: JsonRecord | null = null;
|
let capturedBody: JsonRecord | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -680,9 +680,24 @@ export class CodexReasoningProxy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxErrorResponseSize = 10 * 1024 * 1024; // 10MB
|
||||||
|
let totalResponseBytes = 0;
|
||||||
|
let responseTooLarge = false;
|
||||||
const chunks: Buffer[] = [];
|
const chunks: Buffer[] = [];
|
||||||
upstreamRes.on('data', (chunk: Buffer) => chunks.push(chunk));
|
upstreamRes.on('data', (chunk: Buffer) => {
|
||||||
|
totalResponseBytes += chunk.length;
|
||||||
|
if (totalResponseBytes > maxErrorResponseSize) {
|
||||||
|
responseTooLarge = true;
|
||||||
|
upstreamRes.destroy(new Error('Upstream error response exceeded 10MB limit'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chunks.push(chunk);
|
||||||
|
});
|
||||||
upstreamRes.on('end', async () => {
|
upstreamRes.on('end', async () => {
|
||||||
|
if (responseTooLarge) {
|
||||||
|
reject(new Error('Upstream error response exceeded 10MB limit'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const responseBody = Buffer.concat(chunks).toString('utf8');
|
const responseBody = Buffer.concat(chunks).toString('utf8');
|
||||||
const unsupportedError =
|
const unsupportedError =
|
||||||
|
|||||||
Reference in New Issue
Block a user