test(webhook-github): verify chunked overflow response

This commit is contained in:
Tianyi Cui
2026-08-23 01:48:36 +08:00
parent 2f56345439
commit 2b2a8e8240
@@ -1,5 +1,5 @@
import { createHmac } from 'node:crypto'
import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http'
import { createServer, request as httpRequest, type IncomingMessage, type Server, type ServerResponse } from 'node:http'
import type { AddressInfo } from 'node:net'
import type { Context } from '@deepseek-ai/cordis'
import { afterEach, describe, expect, it, vi } from 'vitest'
@@ -81,6 +81,37 @@ async function post(
})
}
/** Send body chunks without Content-Length through a real Node client socket. */
async function postChunked(
base: string,
chunks: readonly string[],
endDelayMs = 0,
): Promise<{ body: string; status: number }> {
return await new Promise((resolve, reject) => {
const request = httpRequest(base, {
method: 'POST',
headers: {
connection: 'close',
'content-type': 'application/json',
'transfer-encoding': 'chunked',
'x-hub-signature-256': 'sha256=unused',
'x-github-event': 'pull_request',
'x-github-delivery': 'chunked-delivery',
},
}, (response) => {
let body = ''
response.setEncoding('utf8')
response.on('data', (chunk: string) => { body += chunk })
response.on('end', () => { resolve({ body, status: response.statusCode ?? 0 }) })
})
request.once('error', reject)
request.once('socket', (socket) => { socket.setNoDelay(true) })
for (const chunk of chunks) request.write(chunk)
if (endDelayMs === 0) request.end()
else setTimeout(() => { request.end() }, endDelayMs)
})
}
describe('GitHub webhook HTTP handler', () => {
it('verifies, projects, dispatches, and answers 202', async () => {
const fake = fakeContext()
@@ -180,7 +211,7 @@ describe('GitHub webhook HTTP handler', () => {
expect(fake.dispatch).not.toHaveBeenCalled()
})
it('rejects declared and streamed bodies over the configured cap', async () => {
it('rejects a declared body over the configured cap', async () => {
const fake = fakeContext()
const base = await serve(fake.ctx, 2)
const response = await post(base, '{} ')
@@ -188,6 +219,17 @@ describe('GitHub webhook HTTP handler', () => {
expect(fake.dispatch).not.toHaveBeenCalled()
})
it('answers 413 for a chunked body over the cap without resetting the connection', async () => {
const fake = fakeContext()
const base = await serve(fake.ctx, 2)
await expect(postChunked(base, ['abc'], 50)).resolves.toEqual({
body: 'request body is too large',
status: 413,
})
expect(fake.dispatch).not.toHaveBeenCalled()
})
it('answers 503 when the credential or runtime is unavailable', async () => {
const missing = fakeContext()
missing.setSecret(undefined)