dify/cli/test/fixtures/stub-server.ts
L1nSn0w cfc1cf2b8c
refactor(cli/http): replace ky with a self-contained HTTP client (#36711)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 09:04:42 +00:00

67 lines
2.1 KiB
TypeScript

import type { AddressInfo } from 'node:net'
import { Buffer } from 'node:buffer'
import * as http from 'node:http'
// Records what the client actually put on the wire so API-client tests can
// assert method / path / query / body / headers without mocking fetch.
export type CapturedRequest = {
method?: string
url?: string
body?: string
headers?: http.IncomingHttpHeaders
}
export type StubServer = {
readonly url: string
readonly captured: CapturedRequest
readonly stop: () => Promise<void>
}
// Buffers the request body, captures the request line + headers, then replies
// with a JSON payload and a matching Content-Length.
export function jsonResponder(
status: number,
body: unknown,
captured: CapturedRequest,
): http.RequestListener {
return (req, res) => {
captured.method = req.method
captured.url = req.url
captured.headers = req.headers
const chunks: Buffer[] = []
req.on('data', c => chunks.push(c))
req.on('end', () => {
captured.body = Buffer.concat(chunks).toString('utf8')
const payload = JSON.stringify(body)
res.writeHead(status, {
'content-type': 'application/json',
'content-length': Buffer.byteLength(payload),
})
res.end(payload)
})
}
}
// Starts a throwaway loopback server. The handler is built from the same
// `captured` object the caller reads back via `stub.captured`, so there is no
// reassignment dance between the listener and the assertions.
export function startStubServer(
makeHandler: (captured: CapturedRequest) => http.RequestListener,
): Promise<StubServer> {
const captured: CapturedRequest = {}
const handler = makeHandler(captured)
return new Promise((resolve, reject) => {
const server = http.createServer((req, res) => handler(req, res))
server.listen(0, '127.0.0.1', () => {
const addr = server.address() as AddressInfo
resolve({
url: `http://127.0.0.1:${addr.port}`,
captured,
stop: () =>
new Promise<void>((res, rej) => server.close(err => (err ? rej(err) : res()))),
})
})
server.on('error', reject)
})
}