Files
pnpm/pnpm11/network/fetch/test/utils/trickleServer.ts
T
Zoltan Kochan 54d7268c10 fix(network): make fetch-timeout an inactivity timeout (#14642)
pnpm aborted a request once its total time passed `fetchTimeout`, body
included, so `pnpm runtime set node` could never finish its ~62 MB
download on a slow connection. pnpm v12 set reqwest's client-level
`timeout`, a deadline for the whole request; pnpm v11 passed
`AbortSignal.timeout` to undici, which aborts the response body too.

Both stacks now bound inactivity instead. pnpm v12 sets reqwest's
`read_timeout`, which restarts on every chunk received. pnpm v11 drops
the abort signal and lets the undici dispatcher enforce `headersTimeout`
and `bodyTimeout`, which behave the same way; the global dispatcher
sets per dispatch, through an interceptor composed onto the dispatcher
that would have served the request. The agents pnpm builds for a proxy
or custom TLS take their connect bounds from the same value, which the
abort signal used to cover.

A connection that stops delivering data still fails after
`fetchTimeout` in both.

Closes pnpm/pnpm#14604
2026-09-07 11:27:17 +02:00

29 lines
804 B
TypeScript

import { createServer, type ServerResponse } from 'node:http'
import type { AddressInfo } from 'node:net'
export interface TestServer extends AsyncDisposable {
url: string
}
export async function startServer (respond: (res: ServerResponse) => void): Promise<TestServer> {
const server = createServer((_req, res) => {
res.writeHead(200, { 'content-type': 'application/octet-stream' })
respond(res)
})
await new Promise<void>((resolve) => {
server.listen(0, '127.0.0.1', resolve)
})
const { port } = server.address() as AddressInfo
return {
url: `http://127.0.0.1:${port}/`,
async [Symbol.asyncDispose] () {
server.closeAllConnections()
await new Promise<void>((resolve) => {
server.close(() => {
resolve()
})
})
},
}
}