Files
deepseek-harness/scripts/verify-no-bare-dispatcher.spec.ts
T
Yichen Jiang 8470ddef1d refactor(http-proxy): converge the proxy API on four functions
The package exported six functions, four of them shaped by one SDK's
transport each: a dispatcher factory, a `node:http` agent factory, a
proxy-URL lookup, and a policy accessor. Review asked whether the call
sites could converge instead of the package growing an export per SDK.

They could, and each removal took a whole shape with it:

- The OTLP exporter moves to the SDK's `fetch` delegate, retiring
  `createNodeHttpAgent`. Its Node-version floor goes too: `proxyEnv` on
  an `http.Agent` needs 22.21 or 24.5, inside the engines range, so
  telemetry was direct on 22.19, 22.20, and 24.0-24.4. The cost is
  `compression`, a Node-transport option; the plugin now refuses it,
  `keepAlive`, and `httpAgentOptions` at load instead of ignoring them.
- `web-fetch-http` builds its own address-pinning agent under an
  annotated `proxy-exempt:` exemption, retiring `createDispatcher`.
  Pinning is per-request state a process-wide dispatcher cannot hold.
- E2B reads `route.proxy`, retiring `proxyUrlFor`.

What remains is `installProxyFromEnvironment`, `proxyRouteFor`,
`proxyEnvironmentForChild`, and `clearedProxyEnv` — one per way a caller
can need the policy. Installation absorbs resolution and diagnostic
reporting, which no caller needed apart.

`proxyRouteFor` also closes a defect the old accessor made expressible:
`web-fetch-http` read the policy to decide whether to pin, then read it
again to build a transport, so an unmount between the two returned a
direct, unpinned agent for a URL the first read had cleared as proxied.
A route carries the answer and the transport that answer assumed.

Every egress spec now installs through `installProxyFromEnvironment`, so
no test asserts a policy object a real launch could not produce.
2026-09-01 21:15:04 +08:00

144 lines
5.4 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { findDispatcherViolations, scanRepository, DISPATCHER_OWNER } from './verify-no-bare-dispatcher.ts'
const FILE = 'packages/web/web-fetch-http/src/network.ts'
function reasons(source: string, file = FILE): string[] {
return findDispatcherViolations(file, source).map(violation => violation.what)
}
describe('bare dispatcher check', () => {
it('rejects the shape that silently bypassed the proxy before this rule existed', () => {
expect(reasons(`
import { Agent } from 'undici'
const dispatcher = new Agent({ connect: { lookup } })
const response = await fetch(url, { dispatcher })
`)).toEqual(['constructs an undici agent', 'passes an explicit \`dispatcher\`'])
})
it('rejects an explicit dispatcher option however the agent was obtained', () => {
expect(reasons(" const response = await fetch(url, { method: 'GET', dispatcher: pooled })"))
.toEqual(['passes an explicit \`dispatcher\`'])
})
it('rejects a namespaced construction', () => {
expect(reasons(`
import * as undici from 'undici'
const agent = new undici.ProxyAgent(uri)
`)).toEqual(['constructs an undici agent'])
})
it('reports the offending line number and text', () => {
const source = "import { Agent } from 'undici'\nconst a = 1\nconst b = new Agent({})"
expect(findDispatcherViolations(FILE, source)).toEqual([
{ file: FILE, line: 3, what: 'constructs an undici agent', text: 'const b = new Agent({})' },
])
})
it('accepts the sanctioned factory', () => {
expect(reasons(' const route = proxyRouteFor(url)')).toEqual([])
})
it('rejects the shorthand form a line-wise regex misses', () => {
expect(reasons(`
import { Agent } from 'undici'
const dispatcher = pool
const response = await fetch(url, { method: 'GET', dispatcher })
`)).toEqual(['passes an explicit \`dispatcher\`'])
})
it('rejects a quoted dispatcher key', () => {
expect(reasons(" await fetch(url, { 'dispatcher': pooled })"))
.toEqual(['passes an explicit \`dispatcher\`'])
})
it('rejects construction through an import alias', () => {
expect(reasons(`
import { Agent as CustomAgent } from 'undici'
const agent = new CustomAgent({})
`)).toEqual(['constructs an undici agent'])
})
it('rejects a destructured dynamic import, the form this repository loads undici with', () => {
expect(reasons(`
const { Agent } = await import('undici')
const agent = new Agent({})
`)).toEqual(['constructs an undici agent'])
})
it('rejects a renamed binding from a dynamic import', () => {
expect(reasons(`
const { ProxyAgent: Tunnel } = await import('undici')
const agent = new Tunnel({ uri })
`)).toEqual(['constructs an undici agent'])
})
it('rejects a namespace bound by a dynamic import', () => {
expect(reasons(`
const undici = await import('undici')
const agent = new undici.Agent({})
`)).toEqual(['constructs an undici agent'])
})
it('finds a dynamic import nested inside a function, not only at the top level', () => {
expect(reasons(`
export async function requestWith(url) {
const { Agent } = await import('undici')
return new Agent({})
}
`)).toEqual(['constructs an undici agent'])
})
it('accepts a dynamic import of an unrelated module that exports Agent', () => {
expect(reasons(`
const { Agent } = await import('./our-own-agent.ts')
const agent = new Agent({})
`)).toEqual([])
})
it('accepts an unrelated class that happens to be named Agent', () => {
expect(reasons(`
import { Agent } from './our-own-agent.ts'
const agent = new Agent({})
`)).toEqual([])
})
it('accepts an exemption annotated on the line above, where a long line puts it', () => {
expect(reasons(`
import { Agent } from 'undici'
// proxy-exempt: the dispatcher already applied the active policy.
const response = await fetch(url, { method: 'GET', headers, dispatcher })
`)).toEqual([])
})
it('accepts an annotated exemption', () => {
expect(reasons(`
import { Agent } from 'undici'
const agent = new Agent({}) // proxy-exempt: loopback transport for the local test server
`)).toEqual([])
})
it('exempts the package that owns dispatcher construction', () => {
expect(reasons("import { EnvHttpProxyAgent } from 'undici'\nconst agent = new EnvHttpProxyAgent()", `${DISPATCHER_OWNER}src/install.ts`)).toEqual([])
})
it('normalizes native separators before exempting the owning package', () => {
expect(reasons("import { Agent } from 'undici'\nconst agent = new Agent({})", DISPATCHER_OWNER.replaceAll('/', '\\') + 'src\\install.ts')).toEqual([])
})
it('parses only a file naming undici or the dispatcher option', () => {
// The pre-filter that keeps this gate from parsing 1576 of 1597 repository files excludes a
// file mentioning neither word. Both violations require one of them in source, so nothing
// detectable is excluded — the second case proves a violating shape survives the filter.
expect(reasons(' const agent = new Agent({ keepAlive: true })')).toEqual([])
expect(reasons(`
import { Agent } from 'undici'
const agent = new Agent({})
`)).toEqual(['constructs an undici agent'])
})
it('passes on the current tree', () => {
expect(scanRepository()).toEqual([])
})
})