Skip to content

Commit

Permalink
fix(ClientRequest): pass custom agent options in passthrough (#701)
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Solomon <[email protected]>
Co-authored-by: Artem Zakharchenko <[email protected]>
  • Loading branch information
3 people authored Jan 31, 2025
1 parent a9fd7cf commit bcec579
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 10 deletions.
33 changes: 25 additions & 8 deletions src/interceptors/ClientRequest/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {

declare module 'node:http' {
interface Agent {
options?: http.AgentOptions
createConnection(options: any, callback: any): net.Socket
}
}
Expand All @@ -33,15 +34,23 @@ export class MockAgent extends http.Agent {

public createConnection(options: any, callback: any): net.Socket {
const createConnection =
(this.customAgent instanceof http.Agent &&
this.customAgent.createConnection) ||
super.createConnection
this.customAgent instanceof http.Agent
? this.customAgent.createConnection
: super.createConnection

const createConnectionOptions =
this.customAgent instanceof http.Agent
? {
...options,
...this.customAgent.options,
}
: options

const socket = new MockHttpSocket({
connectionOptions: options,
createConnection: createConnection.bind(
this.customAgent || this,
options,
createConnectionOptions,
callback
),
onRequest: this.onRequest.bind(this),
Expand All @@ -66,15 +75,23 @@ export class MockHttpsAgent extends https.Agent {

public createConnection(options: any, callback: any): net.Socket {
const createConnection =
(this.customAgent instanceof https.Agent &&
this.customAgent.createConnection) ||
super.createConnection
this.customAgent instanceof https.Agent
? this.customAgent.createConnection
: super.createConnection

const createConnectionOptions =
this.customAgent instanceof https.Agent
? {
...options,
...this.customAgent.options,
}
: options

const socket = new MockHttpSocket({
connectionOptions: options,
createConnection: createConnection.bind(
this.customAgent || this,
options,
createConnectionOptions,
callback
),
onRequest: this.onRequest.bind(this),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,50 @@ it('sets fallback Agent based on the URL protocol', () => {
expect(agent).toHaveProperty('protocol', url.protocol)
})

it('preserves `requestUnauthorized` option set to undefined', () => {
const [, options] = normalizeClientRequestArgs('https:', [
'https://github.com',
{ rejectUnauthorized: undefined },
])

expect(options.rejectUnauthorized).toBe(undefined)
expect((options.agent as HttpsAgent).options.rejectUnauthorized).toBe(
undefined
)
})

it('preserves `requestUnauthorized` option set to true', () => {
const [, options] = normalizeClientRequestArgs('https:', [
'https://github.com',
{ rejectUnauthorized: true },
])

expect(options.rejectUnauthorized).toBe(true)
expect((options.agent as HttpsAgent).options.rejectUnauthorized).toBe(true)
})

it('preserves `requestUnauthorized` option set to false', () => {
const [, options] = normalizeClientRequestArgs('https:', [
'https://github.com',
{ rejectUnauthorized: false },
])

expect(options.rejectUnauthorized).toBe(false)
expect((options.agent as HttpsAgent).options.rejectUnauthorized).toBe(false)
})

it('does not add `rejectUnauthorized` value if not set', () => {
const agent = new HttpsAgent()
const [, options] = normalizeClientRequestArgs('https:', [
'https://github.com',
])

expect(options).not.toHaveProperty('rejectUnauthorized')
expect((options.agent as HttpsAgent).options).not.toHaveProperty(
'rejectUnauthorized'
)
})

it('does not set any fallback Agent given "agent: false" option', () => {
const [, options] = normalizeClientRequestArgs('https:', [
'https://github.com',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,10 @@ export function normalizeClientRequestArgs(
const agent =
options.protocol === 'https:'
? new HttpsAgent({
rejectUnauthorized: options.rejectUnauthorized,
// Any other value other than false is considered as true, so we don't add this property if undefined.
...('rejectUnauthorized' in options && {
rejectUnauthorized: options.rejectUnauthorized,
}),
})
: new HttpAgent()

Expand Down
2 changes: 1 addition & 1 deletion test/modules/http/compliance/http-custom-agent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ it('preserves the context of the "createConnection" function in a custom http ag
const request = http.get(httpServer.http.url('/resource'), { agent })
await waitForClientRequest(request)

const [context] = createConnectionContextSpy.mock.calls[0]
const [context] = createConnectionContextSpy.mock.calls[0] || []
expect(context.constructor.name).toBe('CustomHttpAgent')
})

Expand Down

0 comments on commit bcec579

Please sign in to comment.