-
-
Notifications
You must be signed in to change notification settings - Fork 119
/
index.ts
123 lines (100 loc) · 3.17 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import http from 'http'
import https from 'https'
import { Interceptor, Observer, Resolver } from '../../createInterceptor'
import { createClientRequestOverride } from './createClientRequestOverride'
const debug = require('debug')('http override')
type Protocol = 'http' | 'https'
type PureModules = Map<
Protocol,
{
module: typeof http | typeof https
get: typeof http.get
request: typeof http.request
}
>
// Store a pointer to the original `http.ClientRequest` class
// so it can be mutated during runtime, affecting any subsequent calls.
let pureClientRequest: typeof http.ClientRequest
function handleClientRequest(
protocol: string,
pureMethod: typeof http.get | typeof http.request,
args: any[],
observer: Observer,
resolver: Resolver
): http.ClientRequest {
// The first time we execute this, I'll save the original ClientRequest.
// This because is used to restore the dafault one later
if (!pureClientRequest) {
pureClientRequest = http.ClientRequest
}
const ClientRequestOverride = createClientRequestOverride({
defaultProtocol: `${protocol}:`,
pureClientRequest,
pureMethod,
observer,
resolver,
})
debug('patching native http.ClientRequest...')
// Only http.ClientRequest is overridden because https uses http
// @ts-ignore
http.ClientRequest = ClientRequestOverride
debug('new http.ClientRequest (origin: %s)', protocol)
// @ts-expect-error Variable call signature.
return new http.ClientRequest(...args)
}
/**
* Intercepts requests issued by native `http` and `https` modules.
*/
export const interceptClientRequest: Interceptor = (observer, resolver) => {
const pureModules: PureModules = new Map()
const modules: Protocol[] = ['http', 'https']
modules.forEach((protocol) => {
const requestModule = protocol === 'https' ? https : http
const { request: originalRequest, get: originalGet } = requestModule
// Wrap an original `http.request`/`https.request`
// so that its invocations can be debugged.
function proxiedOriginalRequest(...args: any[]) {
debug('%s.request original call', protocol)
// @ts-ignore
return originalRequest(...args)
}
debug('patching "%s" module...', protocol)
// @ts-ignore
requestModule.request = function requestOverride(...args: any[]) {
debug('%s.request proxy call', protocol)
return handleClientRequest(
protocol,
proxiedOriginalRequest.bind(requestModule),
args,
observer,
resolver
)
}
// @ts-ignore
requestModule.get = function getOverride(...args: any[]) {
debug('%s.get call', protocol)
const req = handleClientRequest(
protocol,
originalGet.bind(requestModule),
args,
observer,
resolver
)
req.end()
return req
}
pureModules.set(protocol, {
module: requestModule,
request: originalRequest,
get: originalGet,
})
})
return () => {
debug('restoring modules...')
for (const requestModule of pureModules.values()) {
requestModule.module.get = requestModule.get
requestModule.module.request = requestModule.request
}
pureModules.clear()
}
}