@mswjs/interceptors 0.16.6 → 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +181 -57
- package/lib/InteractiveIsomorphicRequest.d.ts +7 -0
- package/lib/InteractiveIsomorphicRequest.js +37 -0
- package/lib/InteractiveIsomorphicRequest.js.map +1 -0
- package/lib/IsomorphicRequest.d.ts +24 -0
- package/lib/IsomorphicRequest.js +107 -0
- package/lib/IsomorphicRequest.js.map +1 -0
- package/lib/RemoteHttpInterceptor.d.ts +1 -1
- package/lib/RemoteHttpInterceptor.js +12 -8
- package/lib/RemoteHttpInterceptor.js.map +1 -1
- package/lib/glossary.d.ts +2 -17
- package/lib/glossary.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +6 -1
- package/lib/index.js.map +1 -1
- package/lib/interceptors/ClientRequest/NodeClientRequest.js +9 -27
- package/lib/interceptors/ClientRequest/NodeClientRequest.js.map +1 -1
- package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js.map +1 -1
- package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.d.ts +1 -2
- package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js +19 -27
- package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js.map +1 -1
- package/lib/interceptors/XMLHttpRequest/index.d.ts +2 -1
- package/lib/interceptors/XMLHttpRequest/index.js.map +1 -1
- package/lib/interceptors/fetch/index.js +22 -25
- package/lib/interceptors/fetch/index.js.map +1 -1
- package/lib/utils/bufferUtils.d.ts +3 -0
- package/lib/utils/bufferUtils.js +20 -0
- package/lib/utils/bufferUtils.js.map +1 -0
- package/package.json +3 -2
- package/src/InteractiveIsomorphicRequest.ts +24 -0
- package/src/IsomorphicRequest.test.ts +106 -0
- package/src/IsomorphicRequest.ts +86 -0
- package/src/RemoteHttpInterceptor.ts +18 -18
- package/src/glossary.ts +2 -19
- package/src/index.ts +3 -0
- package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +2 -8
- package/src/interceptors/ClientRequest/NodeClientRequest.ts +14 -35
- package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +4 -4
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestOverride.ts +21 -23
- package/src/interceptors/XMLHttpRequest/index.ts +2 -5
- package/src/interceptors/fetch/index.ts +28 -19
- package/src/utils/bufferUtils.test.ts +20 -0
- package/src/utils/bufferUtils.ts +19 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Headers } from 'headers-polyfill/lib'
|
|
2
|
+
import { IsomorphicRequest } from './IsomorphicRequest'
|
|
3
|
+
import { encodeBuffer } from './utils/bufferUtils'
|
|
4
|
+
|
|
5
|
+
const url = new URL('http://dummy')
|
|
6
|
+
const body = encodeBuffer(JSON.stringify({ hello: 'world' }))
|
|
7
|
+
|
|
8
|
+
it('reads request body as json', async () => {
|
|
9
|
+
const request = new IsomorphicRequest(url, { body })
|
|
10
|
+
|
|
11
|
+
expect(request.bodyUsed).toBe(false)
|
|
12
|
+
expect(await request.json()).toEqual({ hello: 'world' })
|
|
13
|
+
expect(request.bodyUsed).toBe(true)
|
|
14
|
+
expect(() => request.json()).rejects.toThrow(
|
|
15
|
+
'Failed to execute "json" on "IsomorphicRequest": body buffer already read'
|
|
16
|
+
)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('reads request body as text', async () => {
|
|
20
|
+
const request = new IsomorphicRequest(url, { body })
|
|
21
|
+
|
|
22
|
+
expect(request.bodyUsed).toBe(false)
|
|
23
|
+
expect(await request.text()).toEqual(JSON.stringify({ hello: 'world' }))
|
|
24
|
+
expect(request.bodyUsed).toBe(true)
|
|
25
|
+
expect(() => request.text()).rejects.toThrow(
|
|
26
|
+
'Failed to execute "text" on "IsomorphicRequest": body buffer already read'
|
|
27
|
+
)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('reads request body as array buffer', async () => {
|
|
31
|
+
const request = new IsomorphicRequest(url, { body })
|
|
32
|
+
|
|
33
|
+
expect(request.bodyUsed).toBe(false)
|
|
34
|
+
expect(await request.arrayBuffer()).toEqual(encodeBuffer(`{"hello":"world"}`))
|
|
35
|
+
expect(request.bodyUsed).toBe(true)
|
|
36
|
+
expect(() => request.arrayBuffer()).rejects.toThrow(
|
|
37
|
+
'Failed to execute "arrayBuffer" on "IsomorphicRequest": body buffer already read'
|
|
38
|
+
)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('returns default method', () => {
|
|
42
|
+
const request = new IsomorphicRequest(url, { body })
|
|
43
|
+
expect(request.method).toEqual('GET')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('returns given method', () => {
|
|
47
|
+
const request = new IsomorphicRequest(url, { body, method: 'POST' })
|
|
48
|
+
expect(request.method).toEqual('POST')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('returns given credentials', () => {
|
|
52
|
+
const request = new IsomorphicRequest(url, { body, credentials: 'include' })
|
|
53
|
+
expect(request.credentials).toEqual('include')
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('returns default credentials', () => {
|
|
57
|
+
const request = new IsomorphicRequest(url, { body })
|
|
58
|
+
expect(request.credentials).toEqual('same-origin')
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('returns empty headers if not provided', () => {
|
|
62
|
+
const request = new IsomorphicRequest(url, { body })
|
|
63
|
+
expect(request.headers).toEqual(new Headers())
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('returns given headers', () => {
|
|
67
|
+
const request = new IsomorphicRequest(url, {
|
|
68
|
+
body,
|
|
69
|
+
headers: { 'Content-Type': 'application/json' },
|
|
70
|
+
})
|
|
71
|
+
expect(request.headers).toEqual(
|
|
72
|
+
new Headers({ 'Content-Type': 'application/json' })
|
|
73
|
+
)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('returns a copy of isomorphic request instance', () => {
|
|
77
|
+
const request = new IsomorphicRequest(url, {
|
|
78
|
+
body,
|
|
79
|
+
headers: { foo: 'bar' },
|
|
80
|
+
})
|
|
81
|
+
const derivedRequest = new IsomorphicRequest(request)
|
|
82
|
+
|
|
83
|
+
expect(request.id).toBe(derivedRequest.id)
|
|
84
|
+
expect(request.url.href).toBe(derivedRequest.url.href)
|
|
85
|
+
expect(request['_body']).toEqual(derivedRequest['_body'])
|
|
86
|
+
expect(request.headers).toEqual(derivedRequest.headers)
|
|
87
|
+
expect(request.method).toBe(derivedRequest.method)
|
|
88
|
+
expect(request.credentials).toBe(derivedRequest.credentials)
|
|
89
|
+
expect(request.bodyUsed).toBe(false)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('clones current isomorphic request instance', () => {
|
|
93
|
+
const request = new IsomorphicRequest(url, {
|
|
94
|
+
body,
|
|
95
|
+
headers: { foo: 'bar' },
|
|
96
|
+
})
|
|
97
|
+
const clonedRequest = request.clone()
|
|
98
|
+
|
|
99
|
+
expect(clonedRequest.id).toBe(request.id)
|
|
100
|
+
expect(clonedRequest.method).toBe(request.method)
|
|
101
|
+
expect(clonedRequest.url.href).toBe(request.url.href)
|
|
102
|
+
expect(clonedRequest.headers).toEqual(request.headers)
|
|
103
|
+
expect(clonedRequest.credentials).toBe(request.credentials)
|
|
104
|
+
expect(clonedRequest['_body']).toEqual(request['_body'])
|
|
105
|
+
expect(clonedRequest.bodyUsed).toBe(false)
|
|
106
|
+
})
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Headers } from 'headers-polyfill/lib'
|
|
2
|
+
import { invariant } from 'outvariant'
|
|
3
|
+
import { decodeBuffer } from './utils/bufferUtils'
|
|
4
|
+
import { uuidv4 } from './utils/uuid'
|
|
5
|
+
|
|
6
|
+
export interface RequestInit {
|
|
7
|
+
method?: string
|
|
8
|
+
headers?: Record<string, string | string[]> | Headers
|
|
9
|
+
credentials?: RequestCredentials
|
|
10
|
+
body?: ArrayBuffer
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class IsomorphicRequest {
|
|
14
|
+
public id: string
|
|
15
|
+
public readonly url: URL
|
|
16
|
+
public readonly method: string
|
|
17
|
+
public readonly headers: Headers
|
|
18
|
+
public readonly credentials: RequestCredentials
|
|
19
|
+
|
|
20
|
+
private readonly _body: ArrayBuffer
|
|
21
|
+
private _bodyUsed: boolean
|
|
22
|
+
|
|
23
|
+
constructor(url: URL)
|
|
24
|
+
constructor(url: URL, init: RequestInit)
|
|
25
|
+
constructor(request: IsomorphicRequest)
|
|
26
|
+
constructor(input: IsomorphicRequest | URL, init: RequestInit = {}) {
|
|
27
|
+
const defaultBody = new ArrayBuffer(0)
|
|
28
|
+
this._bodyUsed = false
|
|
29
|
+
|
|
30
|
+
if (input instanceof IsomorphicRequest) {
|
|
31
|
+
this.id = input.id
|
|
32
|
+
this.url = input.url
|
|
33
|
+
this.method = input.method
|
|
34
|
+
this.headers = input.headers
|
|
35
|
+
this.credentials = input.credentials
|
|
36
|
+
this._body = input._body || defaultBody
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.id = uuidv4()
|
|
41
|
+
this.url = input
|
|
42
|
+
this.method = init.method || 'GET'
|
|
43
|
+
this.headers = new Headers(init.headers)
|
|
44
|
+
this.credentials = init.credentials || 'same-origin'
|
|
45
|
+
this._body = init.body || defaultBody
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public get bodyUsed(): boolean {
|
|
49
|
+
return this._bodyUsed
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public async text(): Promise<string> {
|
|
53
|
+
invariant(
|
|
54
|
+
!this.bodyUsed,
|
|
55
|
+
'Failed to execute "text" on "IsomorphicRequest": body buffer already read'
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
this._bodyUsed = true
|
|
59
|
+
return decodeBuffer(this._body)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public async json<T = any>(): Promise<T> {
|
|
63
|
+
invariant(
|
|
64
|
+
!this.bodyUsed,
|
|
65
|
+
'Failed to execute "json" on "IsomorphicRequest": body buffer already read'
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
this._bodyUsed = true
|
|
69
|
+
const text = decodeBuffer(this._body)
|
|
70
|
+
return JSON.parse(text)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public async arrayBuffer(): Promise<ArrayBuffer> {
|
|
74
|
+
invariant(
|
|
75
|
+
!this.bodyUsed,
|
|
76
|
+
'Failed to execute "arrayBuffer" on "IsomorphicRequest": body buffer already read'
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
this._bodyUsed = true
|
|
80
|
+
return this._body
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public clone(): IsomorphicRequest {
|
|
84
|
+
return new IsomorphicRequest(this)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { ChildProcess } from 'child_process'
|
|
2
2
|
import { Headers } from 'headers-polyfill'
|
|
3
|
-
import
|
|
4
|
-
HttpRequestEventMap,
|
|
5
|
-
InteractiveIsomorphicRequest,
|
|
6
|
-
IsomorphicRequest,
|
|
7
|
-
} from './glossary'
|
|
3
|
+
import { HttpRequestEventMap } from './glossary'
|
|
8
4
|
import { Interceptor } from './Interceptor'
|
|
9
5
|
import { BatchInterceptor } from './BatchInterceptor'
|
|
10
6
|
import { ClientRequestInterceptor } from './interceptors/ClientRequest'
|
|
11
7
|
import { XMLHttpRequestInterceptor } from './interceptors/XMLHttpRequest'
|
|
12
|
-
import { createLazyCallback } from './utils/createLazyCallback'
|
|
13
8
|
import { toIsoResponse } from './utils/toIsoResponse'
|
|
9
|
+
import { IsomorphicRequest } from './IsomorphicRequest'
|
|
10
|
+
import { bufferFrom } from './interceptors/XMLHttpRequest/utils/bufferFrom'
|
|
11
|
+
import { InteractiveIsomorphicRequest } from './InteractiveIsomorphicRequest'
|
|
14
12
|
|
|
15
13
|
export class RemoteHttpInterceptor extends BatchInterceptor<
|
|
16
14
|
[ClientRequestInterceptor, XMLHttpRequestInterceptor]
|
|
@@ -59,7 +57,7 @@ export class RemoteHttpInterceptor extends BatchInterceptor<
|
|
|
59
57
|
}
|
|
60
58
|
})
|
|
61
59
|
|
|
62
|
-
// Listen for the mocked
|
|
60
|
+
// Listen for the mocked response message from the parent.
|
|
63
61
|
this.log(
|
|
64
62
|
'add "message" listener to the parent process',
|
|
65
63
|
handleParentMessage
|
|
@@ -118,17 +116,19 @@ export class RemoteHttpResolver extends Interceptor<HttpRequestEventMap> {
|
|
|
118
116
|
return
|
|
119
117
|
}
|
|
120
118
|
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
requestReviver
|
|
124
|
-
)
|
|
119
|
+
const requestJson = JSON.parse(serializedRequest, requestReviver)
|
|
120
|
+
log('parsed intercepted request', requestJson)
|
|
125
121
|
|
|
126
|
-
|
|
122
|
+
const body = bufferFrom(requestJson.body)
|
|
127
123
|
|
|
128
|
-
const
|
|
129
|
-
...
|
|
130
|
-
|
|
131
|
-
}
|
|
124
|
+
const isomorphicRequest = new IsomorphicRequest(requestJson.url, {
|
|
125
|
+
...requestJson,
|
|
126
|
+
body: body.buffer,
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const interactiveIsomorphicRequest = new InteractiveIsomorphicRequest(
|
|
130
|
+
isomorphicRequest
|
|
131
|
+
)
|
|
132
132
|
|
|
133
133
|
this.emitter.emit('request', interactiveIsomorphicRequest)
|
|
134
134
|
await this.emitter.untilIdle('request', ({ args: [request] }) => {
|
|
@@ -143,14 +143,14 @@ export class RemoteHttpResolver extends Interceptor<HttpRequestEventMap> {
|
|
|
143
143
|
const serializedResponse = JSON.stringify(mockedResponse)
|
|
144
144
|
|
|
145
145
|
this.process.send(
|
|
146
|
-
`response:${
|
|
146
|
+
`response:${requestJson.id}:${serializedResponse}`,
|
|
147
147
|
(error) => {
|
|
148
148
|
if (error) {
|
|
149
149
|
return
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
if (mockedResponse) {
|
|
153
|
-
// Emit an
|
|
153
|
+
// Emit an optimistic "response" event at this point,
|
|
154
154
|
// not to rely on the back-and-forth signaling for the sake of the event.
|
|
155
155
|
this.emitter.emit(
|
|
156
156
|
'response',
|
package/src/glossary.ts
CHANGED
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
import type { HeadersObject, Headers } from 'headers-polyfill'
|
|
2
|
-
import type {
|
|
2
|
+
import type { InteractiveIsomorphicRequest } from './InteractiveIsomorphicRequest'
|
|
3
|
+
import type { IsomorphicRequest } from './IsomorphicRequest'
|
|
3
4
|
|
|
4
5
|
export const IS_PATCHED_MODULE: unique symbol = Symbol('isPatchedModule')
|
|
5
6
|
|
|
6
7
|
export type RequestCredentials = 'omit' | 'include' | 'same-origin'
|
|
7
8
|
|
|
8
|
-
export interface IsomorphicRequest {
|
|
9
|
-
id: string
|
|
10
|
-
url: URL
|
|
11
|
-
method: string
|
|
12
|
-
headers: Headers
|
|
13
|
-
/**
|
|
14
|
-
* The value of the request client's "credentials" option
|
|
15
|
-
* or a compatible alternative (i.e. `withCredentials` for `XMLHttpRequest`).
|
|
16
|
-
* Always equals to "omit" in Node.js.
|
|
17
|
-
*/
|
|
18
|
-
credentials: RequestCredentials
|
|
19
|
-
body?: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface InteractiveIsomorphicRequest extends IsomorphicRequest {
|
|
23
|
-
respondWith: LazyCallback<(mockedResponse: MockedResponse) => void>
|
|
24
|
-
}
|
|
25
|
-
|
|
26
9
|
export interface IsomorphicResponse {
|
|
27
10
|
status: number
|
|
28
11
|
statusText: string
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export * from './glossary'
|
|
2
2
|
export * from './Interceptor'
|
|
3
3
|
export * from './BatchInterceptor'
|
|
4
|
+
export * from './IsomorphicRequest'
|
|
5
|
+
export * from './InteractiveIsomorphicRequest'
|
|
4
6
|
|
|
5
7
|
/* Utils */
|
|
6
8
|
export { getCleanUrl } from './utils/getCleanUrl'
|
|
9
|
+
export { encodeBuffer, decodeBuffer } from './utils/bufferUtils'
|
|
@@ -139,10 +139,7 @@ test('emits the ENOTFOUND error connecting to a non-existing hostname given no m
|
|
|
139
139
|
const emitter = new AsyncEventEmitter<HttpRequestEventMap>()
|
|
140
140
|
const request = new NodeClientRequest(
|
|
141
141
|
normalizeClientRequestArgs('http:', 'http://non-existing-url.com'),
|
|
142
|
-
{
|
|
143
|
-
emitter,
|
|
144
|
-
log,
|
|
145
|
-
}
|
|
142
|
+
{ emitter, log }
|
|
146
143
|
)
|
|
147
144
|
|
|
148
145
|
request.on('error', (error: NodeJS.ErrnoException) => {
|
|
@@ -181,10 +178,7 @@ test('does not emit ENOTFOUND error connecting to an inactive server given mocke
|
|
|
181
178
|
const handleError = jest.fn()
|
|
182
179
|
const request = new NodeClientRequest(
|
|
183
180
|
normalizeClientRequestArgs('http:', 'http://non-existing-url.com'),
|
|
184
|
-
{
|
|
185
|
-
emitter,
|
|
186
|
-
log,
|
|
187
|
-
}
|
|
181
|
+
{ emitter, log }
|
|
188
182
|
)
|
|
189
183
|
|
|
190
184
|
emitter.on('request', async (request) => {
|
|
@@ -3,12 +3,7 @@ import type { RequestOptions } from 'http'
|
|
|
3
3
|
import { ClientRequest, IncomingMessage } from 'http'
|
|
4
4
|
import { until } from '@open-draft/until'
|
|
5
5
|
import { Headers, objectToHeaders } from 'headers-polyfill/lib'
|
|
6
|
-
import
|
|
7
|
-
InteractiveIsomorphicRequest,
|
|
8
|
-
IsomorphicRequest,
|
|
9
|
-
MockedResponse,
|
|
10
|
-
} from '../../glossary'
|
|
11
|
-
import { uuidv4 } from '../../utils/uuid'
|
|
6
|
+
import { MockedResponse } from '../../glossary'
|
|
12
7
|
import type { ClientRequestEmitter } from '.'
|
|
13
8
|
import { concatChunkToBuffer } from './utils/concatChunkToBuffer'
|
|
14
9
|
import {
|
|
@@ -21,12 +16,12 @@ import { getIncomingMessageBody } from './utils/getIncomingMessageBody'
|
|
|
21
16
|
import { bodyBufferToString } from './utils/bodyBufferToString'
|
|
22
17
|
import {
|
|
23
18
|
ClientRequestWriteArgs,
|
|
24
|
-
ClientRequestWriteCallback,
|
|
25
19
|
normalizeClientRequestWriteArgs,
|
|
26
20
|
} from './utils/normalizeClientRequestWriteArgs'
|
|
27
21
|
import { cloneIncomingMessage } from './utils/cloneIncomingMessage'
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
22
|
+
import { IsomorphicRequest } from '../../IsomorphicRequest'
|
|
23
|
+
import { InteractiveIsomorphicRequest } from '../../InteractiveIsomorphicRequest'
|
|
24
|
+
import { getArrayBuffer } from '../../utils/bufferUtils'
|
|
30
25
|
|
|
31
26
|
export type Protocol = 'http' | 'https'
|
|
32
27
|
|
|
@@ -116,20 +111,9 @@ export class NodeClientRequest extends ClientRequest {
|
|
|
116
111
|
|
|
117
112
|
const requestBody = this.getRequestBody(chunk)
|
|
118
113
|
const isomorphicRequest = this.toIsomorphicRequest(requestBody)
|
|
119
|
-
const interactiveIsomorphicRequest
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
maxCalls: 1,
|
|
123
|
-
maxCallsCallback() {
|
|
124
|
-
invariant(
|
|
125
|
-
false,
|
|
126
|
-
'Failed to respond to "%s %s" request: the "request" event has already been responded to.',
|
|
127
|
-
isomorphicRequest.method,
|
|
128
|
-
isomorphicRequest.url.href
|
|
129
|
-
)
|
|
130
|
-
},
|
|
131
|
-
}),
|
|
132
|
-
}
|
|
114
|
+
const interactiveIsomorphicRequest = new InteractiveIsomorphicRequest(
|
|
115
|
+
isomorphicRequest
|
|
116
|
+
)
|
|
133
117
|
|
|
134
118
|
// Notify the interceptor about the request.
|
|
135
119
|
// This will call any "request" listeners the users have.
|
|
@@ -377,7 +361,7 @@ export class NodeClientRequest extends ClientRequest {
|
|
|
377
361
|
this.agent.destroy()
|
|
378
362
|
}
|
|
379
363
|
|
|
380
|
-
private getRequestBody(chunk: ClientRequestEndChunk | null):
|
|
364
|
+
private getRequestBody(chunk: ClientRequestEndChunk | null): ArrayBuffer {
|
|
381
365
|
const writtenRequestBody = bodyBufferToString(
|
|
382
366
|
Buffer.concat(this.requestBody)
|
|
383
367
|
)
|
|
@@ -388,16 +372,13 @@ export class NodeClientRequest extends ClientRequest {
|
|
|
388
372
|
this.requestBody = concatChunkToBuffer(chunk, this.requestBody)
|
|
389
373
|
}
|
|
390
374
|
|
|
391
|
-
const resolvedRequestBody =
|
|
392
|
-
Buffer.concat(this.requestBody)
|
|
393
|
-
)
|
|
394
|
-
|
|
375
|
+
const resolvedRequestBody = Buffer.concat(this.requestBody)
|
|
395
376
|
this.log('resolved request body:', resolvedRequestBody)
|
|
396
377
|
|
|
397
|
-
return resolvedRequestBody
|
|
378
|
+
return getArrayBuffer(resolvedRequestBody)
|
|
398
379
|
}
|
|
399
380
|
|
|
400
|
-
private toIsomorphicRequest(body:
|
|
381
|
+
private toIsomorphicRequest(body: ArrayBuffer): IsomorphicRequest {
|
|
401
382
|
this.log('creating isomorphic request object...')
|
|
402
383
|
|
|
403
384
|
const outgoingHeaders = this.getHeaders()
|
|
@@ -412,14 +393,12 @@ export class NodeClientRequest extends ClientRequest {
|
|
|
412
393
|
headers.set(headerName.toLowerCase(), headerValue.toString())
|
|
413
394
|
}
|
|
414
395
|
|
|
415
|
-
const isomorphicRequest
|
|
416
|
-
|
|
417
|
-
url: this.url,
|
|
396
|
+
const isomorphicRequest = new IsomorphicRequest(this.url, {
|
|
397
|
+
body,
|
|
418
398
|
method: this.options.method || 'GET',
|
|
419
399
|
credentials: 'same-origin',
|
|
420
400
|
headers,
|
|
421
|
-
|
|
422
|
-
}
|
|
401
|
+
})
|
|
423
402
|
|
|
424
403
|
this.log('successfully created isomorphic request!', isomorphicRequest)
|
|
425
404
|
return isomorphicRequest
|
|
@@ -25,16 +25,16 @@ export function getIncomingMessageBody(
|
|
|
25
25
|
stream.setEncoding(encoding)
|
|
26
26
|
log('using encoding:', encoding)
|
|
27
27
|
|
|
28
|
-
let body = ''
|
|
28
|
+
let body = ''
|
|
29
29
|
|
|
30
30
|
stream.on('data', (responseBody) => {
|
|
31
31
|
log('response body read:', responseBody)
|
|
32
|
-
body += responseBody
|
|
32
|
+
body += responseBody
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
stream.once('end', () => {
|
|
36
|
-
log('response body end')
|
|
37
|
-
resolve(body)
|
|
36
|
+
log('response body end')
|
|
37
|
+
resolve(body)
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
stream.once('error', (error) => {
|
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
headersToString,
|
|
12
12
|
} from 'headers-polyfill'
|
|
13
13
|
import { DOMParser } from '@xmldom/xmldom'
|
|
14
|
-
import { InteractiveIsomorphicRequest, IsomorphicRequest } from '../../glossary'
|
|
15
14
|
import { parseJson } from '../../utils/parseJson'
|
|
16
15
|
import { toIsoResponse } from '../../utils/toIsoResponse'
|
|
17
|
-
import { uuidv4 } from '../../utils/uuid'
|
|
18
16
|
import { bufferFrom } from './utils/bufferFrom'
|
|
19
17
|
import { createEvent } from './utils/createEvent'
|
|
20
18
|
import type { XMLHttpRequestEmitter } from '.'
|
|
21
|
-
import {
|
|
19
|
+
import { IsomorphicRequest } from '../../IsomorphicRequest'
|
|
20
|
+
import { encodeBuffer } from '../../utils/bufferUtils'
|
|
21
|
+
import { InteractiveIsomorphicRequest } from '../../InteractiveIsomorphicRequest'
|
|
22
22
|
|
|
23
23
|
type XMLHttpRequestEventHandler = (
|
|
24
24
|
this: XMLHttpRequest,
|
|
@@ -84,7 +84,6 @@ export const createXMLHttpRequestOverride = (
|
|
|
84
84
|
public statusText: string
|
|
85
85
|
public user?: string
|
|
86
86
|
public password?: string
|
|
87
|
-
public data: string
|
|
88
87
|
public async?: boolean
|
|
89
88
|
public response: any
|
|
90
89
|
public responseText: string
|
|
@@ -132,7 +131,6 @@ export const createXMLHttpRequestOverride = (
|
|
|
132
131
|
this.withCredentials = false
|
|
133
132
|
this.status = 200
|
|
134
133
|
this.statusText = 'OK'
|
|
135
|
-
this.data = ''
|
|
136
134
|
this.response = ''
|
|
137
135
|
this.responseType = 'text'
|
|
138
136
|
this.responseText = ''
|
|
@@ -154,7 +152,7 @@ export const createXMLHttpRequestOverride = (
|
|
|
154
152
|
this.readyState = nextState
|
|
155
153
|
|
|
156
154
|
if (nextState !== this.UNSENT) {
|
|
157
|
-
this.log('
|
|
155
|
+
this.log('triggering readystate change...')
|
|
158
156
|
this.trigger('readystatechange')
|
|
159
157
|
}
|
|
160
158
|
}
|
|
@@ -195,7 +193,6 @@ export const createXMLHttpRequestOverride = (
|
|
|
195
193
|
this.setReadyState(this.UNSENT)
|
|
196
194
|
this.status = 200
|
|
197
195
|
this.statusText = 'OK'
|
|
198
|
-
this.data = ''
|
|
199
196
|
this.response = null as any
|
|
200
197
|
this.responseText = null as any
|
|
201
198
|
this.responseXML = null as any
|
|
@@ -229,10 +226,14 @@ export const createXMLHttpRequestOverride = (
|
|
|
229
226
|
}
|
|
230
227
|
}
|
|
231
228
|
|
|
232
|
-
public send(data?: string) {
|
|
229
|
+
public send(data?: string | ArrayBuffer) {
|
|
233
230
|
this.log('send %s %s', this.method, this.url)
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
let buffer: ArrayBuffer
|
|
232
|
+
if (typeof data === 'string') {
|
|
233
|
+
buffer = encodeBuffer(data)
|
|
234
|
+
} else {
|
|
235
|
+
buffer = data || new ArrayBuffer(0)
|
|
236
|
+
}
|
|
236
237
|
|
|
237
238
|
let url: URL
|
|
238
239
|
|
|
@@ -248,19 +249,16 @@ export const createXMLHttpRequestOverride = (
|
|
|
248
249
|
this.log('request headers', this._requestHeaders)
|
|
249
250
|
|
|
250
251
|
// Create an intercepted request instance exposed to the request intercepting middleware.
|
|
251
|
-
const isomorphicRequest
|
|
252
|
-
|
|
253
|
-
url,
|
|
252
|
+
const isomorphicRequest = new IsomorphicRequest(url, {
|
|
253
|
+
body: buffer,
|
|
254
254
|
method: this.method,
|
|
255
255
|
headers: this._requestHeaders,
|
|
256
256
|
credentials: this.withCredentials ? 'include' : 'omit',
|
|
257
|
-
|
|
258
|
-
}
|
|
257
|
+
})
|
|
259
258
|
|
|
260
|
-
const interactiveIsomorphicRequest
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
259
|
+
const interactiveIsomorphicRequest = new InteractiveIsomorphicRequest(
|
|
260
|
+
isomorphicRequest
|
|
261
|
+
)
|
|
264
262
|
|
|
265
263
|
this.log(
|
|
266
264
|
'emitting the "request" event for %d listener(s)...',
|
|
@@ -331,8 +329,8 @@ export const createXMLHttpRequestOverride = (
|
|
|
331
329
|
if (mockedResponse.body && this.response) {
|
|
332
330
|
this.setReadyState(this.LOADING)
|
|
333
331
|
|
|
334
|
-
//
|
|
335
|
-
//
|
|
332
|
+
// Presence of the mocked response implies a response body (not null).
|
|
333
|
+
// Presence of the coerced `this.response` implies the mocked body is valid.
|
|
336
334
|
const bodyBuffer = bufferFrom(mockedResponse.body)
|
|
337
335
|
|
|
338
336
|
// Trigger a progress event based on the mocked response body.
|
|
@@ -428,8 +426,8 @@ export const createXMLHttpRequestOverride = (
|
|
|
428
426
|
originalRequest.timeout = this.timeout
|
|
429
427
|
}
|
|
430
428
|
|
|
431
|
-
this.log('send',
|
|
432
|
-
originalRequest.send(
|
|
429
|
+
this.log('send', data)
|
|
430
|
+
originalRequest.send(data)
|
|
433
431
|
}
|
|
434
432
|
})
|
|
435
433
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { invariant } from 'outvariant'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
InteractiveIsomorphicRequest,
|
|
5
|
-
IS_PATCHED_MODULE,
|
|
6
|
-
} from '../../glossary'
|
|
2
|
+
import { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'
|
|
3
|
+
import { InteractiveIsomorphicRequest } from '../../InteractiveIsomorphicRequest'
|
|
7
4
|
import { Interceptor } from '../../Interceptor'
|
|
8
5
|
import { AsyncEventEmitter } from '../../utils/AsyncEventEmitter'
|
|
9
6
|
import { createXMLHttpRequestOverride } from './XMLHttpRequestOverride'
|