@mswjs/interceptors 0.31.1 → 0.32.1
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 +56 -39
- package/lib/node/RemoteHttpInterceptor.d.ts +1 -2
- package/lib/node/RemoteHttpInterceptor.js +11 -11
- package/lib/node/RemoteHttpInterceptor.mjs +5 -5
- package/lib/node/{chunk-LTEXDYJ6.js → chunk-2COJKQQB.js} +3 -3
- package/lib/node/chunk-3OJLYEWA.mjs +963 -0
- package/lib/node/chunk-3OJLYEWA.mjs.map +1 -0
- package/lib/node/chunk-5JMJ55U7.js +963 -0
- package/lib/node/chunk-5JMJ55U7.js.map +1 -0
- package/lib/node/{chunk-E4AC7YAC.js → chunk-BFLYGQ6D.js} +4 -2
- package/lib/node/{chunk-KSHIDGUL.mjs → chunk-DV4PBH4D.mjs} +3 -3
- package/lib/node/{chunk-OUWBQF3Z.mjs → chunk-KWV3JXSI.mjs} +14 -14
- package/lib/node/chunk-KWV3JXSI.mjs.map +1 -0
- package/lib/node/{chunk-6FRASLM3.mjs → chunk-PNWPIDEL.mjs} +2 -2
- package/lib/node/{chunk-APT7KA3B.js → chunk-PYD4E2EJ.js} +13 -13
- package/lib/node/{chunk-Q7POAM5N.mjs → chunk-TGTPXCLF.mjs} +3 -1
- package/lib/node/{chunk-MQJ3JOOK.js → chunk-UXCYRE4F.js} +14 -14
- package/lib/node/chunk-UXCYRE4F.js.map +1 -0
- package/lib/node/index.js +3 -3
- package/lib/node/index.mjs +2 -2
- package/lib/node/interceptors/ClientRequest/index.d.ts +83 -14
- package/lib/node/interceptors/ClientRequest/index.js +4 -4
- package/lib/node/interceptors/ClientRequest/index.mjs +3 -3
- package/lib/node/interceptors/XMLHttpRequest/index.js +4 -4
- package/lib/node/interceptors/XMLHttpRequest/index.mjs +3 -3
- package/lib/node/interceptors/fetch/index.js +10 -10
- package/lib/node/interceptors/fetch/index.mjs +2 -2
- package/lib/node/presets/node.d.ts +2 -3
- package/lib/node/presets/node.js +6 -6
- package/lib/node/presets/node.mjs +4 -4
- package/package.json +2 -2
- package/src/interceptors/ClientRequest/MockHttpSocket.ts +595 -0
- package/src/interceptors/ClientRequest/agents.ts +78 -0
- package/src/interceptors/ClientRequest/index.test.ts +14 -12
- package/src/interceptors/ClientRequest/index.ts +200 -41
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.test.ts +78 -98
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestArgs.ts +40 -22
- package/src/interceptors/Socket/MockSocket.test.ts +264 -0
- package/src/interceptors/Socket/MockSocket.ts +59 -0
- package/src/interceptors/Socket/utils/baseUrlFromConnectionOptions.ts +26 -0
- package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.test.ts +52 -0
- package/src/interceptors/Socket/utils/normalizeSocketWriteArgs.ts +33 -0
- package/src/interceptors/Socket/utils/parseRawHeaders.ts +10 -0
- package/lib/node/chunk-IS3CIGXU.js +0 -909
- package/lib/node/chunk-IS3CIGXU.js.map +0 -1
- package/lib/node/chunk-MQJ3JOOK.js.map +0 -1
- package/lib/node/chunk-OMOWHUE6.mjs +0 -909
- package/lib/node/chunk-OMOWHUE6.mjs.map +0 -1
- package/lib/node/chunk-OUWBQF3Z.mjs.map +0 -1
- package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +0 -206
- package/src/interceptors/ClientRequest/NodeClientRequest.ts +0 -680
- package/src/interceptors/ClientRequest/http.get.ts +0 -30
- package/src/interceptors/ClientRequest/http.request.ts +0 -27
- package/src/interceptors/ClientRequest/utils/cloneIncomingMessage.test.ts +0 -26
- package/src/interceptors/ClientRequest/utils/cloneIncomingMessage.ts +0 -74
- package/src/interceptors/ClientRequest/utils/createRequest.test.ts +0 -144
- package/src/interceptors/ClientRequest/utils/createRequest.ts +0 -51
- package/src/interceptors/ClientRequest/utils/createResponse.test.ts +0 -53
- package/src/interceptors/ClientRequest/utils/createResponse.ts +0 -55
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.test.ts +0 -41
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.ts +0 -53
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.test.ts +0 -36
- package/src/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.ts +0 -39
- /package/lib/node/{chunk-LTEXDYJ6.js.map → chunk-2COJKQQB.js.map} +0 -0
- /package/lib/node/{chunk-E4AC7YAC.js.map → chunk-BFLYGQ6D.js.map} +0 -0
- /package/lib/node/{chunk-KSHIDGUL.mjs.map → chunk-DV4PBH4D.mjs.map} +0 -0
- /package/lib/node/{chunk-6FRASLM3.mjs.map → chunk-PNWPIDEL.mjs.map} +0 -0
- /package/lib/node/{chunk-APT7KA3B.js.map → chunk-PYD4E2EJ.js.map} +0 -0
- /package/lib/node/{chunk-Q7POAM5N.mjs.map → chunk-TGTPXCLF.mjs.map} +0 -0
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { ClientRequest } from 'http'
|
|
2
|
-
import { Logger } from '@open-draft/logger'
|
|
3
|
-
import {
|
|
4
|
-
NodeClientOptions,
|
|
5
|
-
NodeClientRequest,
|
|
6
|
-
Protocol,
|
|
7
|
-
} from './NodeClientRequest'
|
|
8
|
-
import {
|
|
9
|
-
normalizeClientRequestArgs,
|
|
10
|
-
ClientRequestArgs,
|
|
11
|
-
} from './utils/normalizeClientRequestArgs'
|
|
12
|
-
|
|
13
|
-
const logger = new Logger('http request')
|
|
14
|
-
|
|
15
|
-
export function request(protocol: Protocol, options: NodeClientOptions) {
|
|
16
|
-
return function interceptorsHttpRequest(
|
|
17
|
-
...args: ClientRequestArgs
|
|
18
|
-
): ClientRequest {
|
|
19
|
-
logger.info('request call (protocol "%s"):', protocol, args)
|
|
20
|
-
|
|
21
|
-
const clientRequestArgs = normalizeClientRequestArgs(
|
|
22
|
-
`${protocol}:`,
|
|
23
|
-
...args
|
|
24
|
-
)
|
|
25
|
-
return new NodeClientRequest(clientRequestArgs, options)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { it, expect } from 'vitest'
|
|
2
|
-
import { Socket } from 'net'
|
|
3
|
-
import { IncomingMessage } from 'http'
|
|
4
|
-
import { Stream, Readable, EventEmitter } from 'stream'
|
|
5
|
-
import { cloneIncomingMessage, IS_CLONE } from './cloneIncomingMessage'
|
|
6
|
-
|
|
7
|
-
it('clones a given IncomingMessage', () => {
|
|
8
|
-
const message = new IncomingMessage(new Socket())
|
|
9
|
-
message.statusCode = 200
|
|
10
|
-
message.statusMessage = 'OK'
|
|
11
|
-
message.headers = { 'x-powered-by': 'msw' }
|
|
12
|
-
const clone = cloneIncomingMessage(message)
|
|
13
|
-
|
|
14
|
-
// Prototypes must be preserved.
|
|
15
|
-
expect(clone).toBeInstanceOf(IncomingMessage)
|
|
16
|
-
expect(clone).toBeInstanceOf(EventEmitter)
|
|
17
|
-
expect(clone).toBeInstanceOf(Stream)
|
|
18
|
-
expect(clone).toBeInstanceOf(Readable)
|
|
19
|
-
|
|
20
|
-
expect(clone.statusCode).toEqual(200)
|
|
21
|
-
expect(clone.statusMessage).toEqual('OK')
|
|
22
|
-
expect(clone.headers).toHaveProperty('x-powered-by', 'msw')
|
|
23
|
-
|
|
24
|
-
// Cloned IncomingMessage must be marked respectively.
|
|
25
|
-
expect(clone[IS_CLONE]).toEqual(true)
|
|
26
|
-
})
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage } from 'http'
|
|
2
|
-
import { PassThrough } from 'stream'
|
|
3
|
-
|
|
4
|
-
export const IS_CLONE = Symbol('isClone')
|
|
5
|
-
|
|
6
|
-
export interface ClonedIncomingMessage extends IncomingMessage {
|
|
7
|
-
[IS_CLONE]: boolean
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Clones a given `http.IncomingMessage` instance.
|
|
12
|
-
*/
|
|
13
|
-
export function cloneIncomingMessage(
|
|
14
|
-
message: IncomingMessage
|
|
15
|
-
): ClonedIncomingMessage {
|
|
16
|
-
const clone = message.pipe(new PassThrough())
|
|
17
|
-
|
|
18
|
-
// Inherit all direct "IncomingMessage" properties.
|
|
19
|
-
inheritProperties(message, clone)
|
|
20
|
-
|
|
21
|
-
// Deeply inherit the message prototypes (Readable, Stream, EventEmitter, etc.).
|
|
22
|
-
const clonedPrototype = Object.create(IncomingMessage.prototype)
|
|
23
|
-
getPrototypes(clone).forEach((prototype) => {
|
|
24
|
-
inheritProperties(prototype, clonedPrototype)
|
|
25
|
-
})
|
|
26
|
-
Object.setPrototypeOf(clone, clonedPrototype)
|
|
27
|
-
|
|
28
|
-
Object.defineProperty(clone, IS_CLONE, {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
value: true,
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
return clone as unknown as ClonedIncomingMessage
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Returns a list of all prototypes the given object extends.
|
|
38
|
-
*/
|
|
39
|
-
function getPrototypes(source: object): object[] {
|
|
40
|
-
const prototypes: object[] = []
|
|
41
|
-
let current = source
|
|
42
|
-
|
|
43
|
-
while ((current = Object.getPrototypeOf(current))) {
|
|
44
|
-
prototypes.push(current)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return prototypes
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Inherits a given target object properties and symbols
|
|
52
|
-
* onto the given source object.
|
|
53
|
-
* @param source Object which should acquire properties.
|
|
54
|
-
* @param target Object to inherit the properties from.
|
|
55
|
-
*/
|
|
56
|
-
function inheritProperties(source: object, target: object): void {
|
|
57
|
-
const properties = [
|
|
58
|
-
...Object.getOwnPropertyNames(source),
|
|
59
|
-
...Object.getOwnPropertySymbols(source),
|
|
60
|
-
]
|
|
61
|
-
|
|
62
|
-
for (const property of properties) {
|
|
63
|
-
if (target.hasOwnProperty(property)) {
|
|
64
|
-
continue
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const descriptor = Object.getOwnPropertyDescriptor(source, property)
|
|
68
|
-
if (!descriptor) {
|
|
69
|
-
continue
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
Object.defineProperty(target, property, descriptor)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { it, expect } from 'vitest'
|
|
2
|
-
import { Logger } from '@open-draft/logger'
|
|
3
|
-
import { HttpRequestEventMap } from '../../..'
|
|
4
|
-
import { NodeClientRequest } from '../NodeClientRequest'
|
|
5
|
-
import { createRequest } from './createRequest'
|
|
6
|
-
import { Emitter } from 'strict-event-emitter'
|
|
7
|
-
|
|
8
|
-
const emitter = new Emitter<HttpRequestEventMap>()
|
|
9
|
-
const logger = new Logger('test')
|
|
10
|
-
|
|
11
|
-
it('creates a fetch Request with a JSON body', async () => {
|
|
12
|
-
const clientRequest = new NodeClientRequest(
|
|
13
|
-
[
|
|
14
|
-
new URL('https://api.github.com'),
|
|
15
|
-
{
|
|
16
|
-
method: 'POST',
|
|
17
|
-
headers: {
|
|
18
|
-
'Content-Type': 'application/json',
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
() => {},
|
|
22
|
-
],
|
|
23
|
-
{
|
|
24
|
-
emitter,
|
|
25
|
-
logger,
|
|
26
|
-
}
|
|
27
|
-
)
|
|
28
|
-
clientRequest.write(JSON.stringify({ firstName: 'John' }))
|
|
29
|
-
|
|
30
|
-
const request = createRequest(clientRequest)
|
|
31
|
-
|
|
32
|
-
expect(request.method).toBe('POST')
|
|
33
|
-
expect(request.url).toBe('https://api.github.com/')
|
|
34
|
-
expect(request.headers.get('Content-Type')).toBe('application/json')
|
|
35
|
-
expect(await request.json()).toEqual({ firstName: 'John' })
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('creates a fetch Request with an empty body', async () => {
|
|
39
|
-
const clientRequest = new NodeClientRequest(
|
|
40
|
-
[
|
|
41
|
-
new URL('https://api.github.com'),
|
|
42
|
-
{
|
|
43
|
-
method: 'GET',
|
|
44
|
-
headers: {
|
|
45
|
-
Accept: 'application/json',
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
() => {},
|
|
49
|
-
],
|
|
50
|
-
{
|
|
51
|
-
emitter,
|
|
52
|
-
logger,
|
|
53
|
-
}
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
const request = createRequest(clientRequest)
|
|
57
|
-
|
|
58
|
-
expect(request.method).toBe('GET')
|
|
59
|
-
expect(request.url).toBe('https://api.github.com/')
|
|
60
|
-
expect(request.headers.get('Accept')).toBe('application/json')
|
|
61
|
-
expect(request.body).toBe(null)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
it('creates a fetch Request with an empty string body', async () => {
|
|
65
|
-
const clientRequest = new NodeClientRequest(
|
|
66
|
-
[
|
|
67
|
-
new URL('https://api.github.com'),
|
|
68
|
-
{
|
|
69
|
-
method: 'HEAD',
|
|
70
|
-
},
|
|
71
|
-
() => {},
|
|
72
|
-
],
|
|
73
|
-
{
|
|
74
|
-
emitter,
|
|
75
|
-
logger,
|
|
76
|
-
}
|
|
77
|
-
)
|
|
78
|
-
clientRequest.write('')
|
|
79
|
-
|
|
80
|
-
const request = createRequest(clientRequest)
|
|
81
|
-
|
|
82
|
-
expect(request.method).toBe('HEAD')
|
|
83
|
-
expect(request.url).toBe('https://api.github.com/')
|
|
84
|
-
expect(request.body).toBe(null)
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
it('creates a fetch Request with an empty password', async () => {
|
|
88
|
-
const clientRequest = new NodeClientRequest(
|
|
89
|
-
[
|
|
90
|
-
new URL('https://api.github.com'),
|
|
91
|
-
{ auth: 'username:' },
|
|
92
|
-
() => {},
|
|
93
|
-
],
|
|
94
|
-
{
|
|
95
|
-
emitter,
|
|
96
|
-
logger,
|
|
97
|
-
}
|
|
98
|
-
)
|
|
99
|
-
clientRequest.write('')
|
|
100
|
-
|
|
101
|
-
const request = createRequest(clientRequest)
|
|
102
|
-
|
|
103
|
-
expect(request.headers.get('Authorization')).toBe(`Basic ${btoa('username:')}`)
|
|
104
|
-
expect(request.url).toBe('https://api.github.com/')
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it('creates a fetch Request with an empty username', async () => {
|
|
108
|
-
const clientRequest = new NodeClientRequest(
|
|
109
|
-
[
|
|
110
|
-
new URL('https://api.github.com'),
|
|
111
|
-
{ auth: ':password' },
|
|
112
|
-
() => {},
|
|
113
|
-
],
|
|
114
|
-
{
|
|
115
|
-
emitter,
|
|
116
|
-
logger,
|
|
117
|
-
}
|
|
118
|
-
)
|
|
119
|
-
clientRequest.write('')
|
|
120
|
-
|
|
121
|
-
const request = createRequest(clientRequest)
|
|
122
|
-
|
|
123
|
-
expect(request.headers.get('Authorization')).toBe(`Basic ${btoa(':password')}`)
|
|
124
|
-
expect(request.url).toBe('https://api.github.com/')
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('creates a fetch Request with falsy headers', async () => {
|
|
128
|
-
const clientRequest = new NodeClientRequest(
|
|
129
|
-
[
|
|
130
|
-
new URL('https://api.github.com'),
|
|
131
|
-
{ headers: { 'foo': 0, 'empty': '' }}
|
|
132
|
-
],
|
|
133
|
-
{
|
|
134
|
-
emitter,
|
|
135
|
-
logger,
|
|
136
|
-
}
|
|
137
|
-
)
|
|
138
|
-
clientRequest.write('')
|
|
139
|
-
|
|
140
|
-
const request = createRequest(clientRequest)
|
|
141
|
-
|
|
142
|
-
expect(request.headers.get('foo')).toBe('0')
|
|
143
|
-
expect(request.headers.get('empty')).toBe('')
|
|
144
|
-
})
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { NodeClientRequest } from '../NodeClientRequest'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates a Fetch API `Request` instance from the given `http.ClientRequest`.
|
|
5
|
-
*/
|
|
6
|
-
export function createRequest(clientRequest: NodeClientRequest): Request {
|
|
7
|
-
const headers = new Headers()
|
|
8
|
-
|
|
9
|
-
const outgoingHeaders = clientRequest.getHeaders()
|
|
10
|
-
for (const headerName in outgoingHeaders) {
|
|
11
|
-
const headerValue = outgoingHeaders[headerName]
|
|
12
|
-
|
|
13
|
-
if (typeof headerValue === 'undefined') {
|
|
14
|
-
continue
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const valuesList = Array.prototype.concat([], headerValue)
|
|
18
|
-
for (const value of valuesList) {
|
|
19
|
-
headers.append(headerName, value.toString())
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Translate the authentication from the request URL to
|
|
25
|
-
* the request "Authorization" header.
|
|
26
|
-
* @see https://github.com/mswjs/interceptors/issues/438
|
|
27
|
-
*/
|
|
28
|
-
if (clientRequest.url.username || clientRequest.url.password) {
|
|
29
|
-
const username = decodeURIComponent(clientRequest.url.username || '')
|
|
30
|
-
const password = decodeURIComponent(clientRequest.url.password || '')
|
|
31
|
-
const auth = `${username}:${password}`
|
|
32
|
-
headers.set('Authorization', `Basic ${btoa(auth)}`)
|
|
33
|
-
|
|
34
|
-
// Remove the credentials from the URL since you cannot
|
|
35
|
-
// construct a Request instance with such a URL.
|
|
36
|
-
clientRequest.url.username = ''
|
|
37
|
-
clientRequest.url.password = ''
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const method = clientRequest.method || 'GET'
|
|
41
|
-
|
|
42
|
-
return new Request(clientRequest.url, {
|
|
43
|
-
method,
|
|
44
|
-
headers,
|
|
45
|
-
credentials: 'same-origin',
|
|
46
|
-
body:
|
|
47
|
-
method === 'HEAD' || method === 'GET'
|
|
48
|
-
? null
|
|
49
|
-
: clientRequest.requestBuffer,
|
|
50
|
-
})
|
|
51
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { it, expect } from 'vitest'
|
|
2
|
-
import { Socket } from 'net'
|
|
3
|
-
import * as http from 'http'
|
|
4
|
-
import { createResponse } from './createResponse'
|
|
5
|
-
import { RESPONSE_STATUS_CODES_WITHOUT_BODY } from '../../../utils/responseUtils'
|
|
6
|
-
|
|
7
|
-
it('creates a fetch api response from http incoming message', async () => {
|
|
8
|
-
const message = new http.IncomingMessage(new Socket())
|
|
9
|
-
message.statusCode = 201
|
|
10
|
-
message.statusMessage = 'Created'
|
|
11
|
-
message.headers['content-type'] = 'application/json'
|
|
12
|
-
|
|
13
|
-
const response = createResponse(message)
|
|
14
|
-
|
|
15
|
-
message.emit('data', Buffer.from('{"firstName":'))
|
|
16
|
-
message.emit('data', Buffer.from('"John"}'))
|
|
17
|
-
message.emit('end')
|
|
18
|
-
|
|
19
|
-
expect(response.status).toBe(201)
|
|
20
|
-
expect(response.statusText).toBe('Created')
|
|
21
|
-
expect(response.headers.get('content-type')).toBe('application/json')
|
|
22
|
-
expect(await response.json()).toEqual({ firstName: 'John' })
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @note Ignore 1xx response status code because those cannot
|
|
27
|
-
* be used as the init to the "Response" constructor.
|
|
28
|
-
*/
|
|
29
|
-
const CONSTRUCTABLE_RESPONSE_STATUS_CODES = Array.from(
|
|
30
|
-
RESPONSE_STATUS_CODES_WITHOUT_BODY
|
|
31
|
-
).filter((status) => status >= 200)
|
|
32
|
-
|
|
33
|
-
it.each(CONSTRUCTABLE_RESPONSE_STATUS_CODES)(
|
|
34
|
-
'ignores message body for %i response status',
|
|
35
|
-
(responseStatus) => {
|
|
36
|
-
const message = new http.IncomingMessage(new Socket())
|
|
37
|
-
message.statusCode = responseStatus
|
|
38
|
-
|
|
39
|
-
const response = createResponse(message)
|
|
40
|
-
|
|
41
|
-
// These chunks will be ignored: this response
|
|
42
|
-
// cannot have body. We don't forward this error to
|
|
43
|
-
// the consumer because it's us who converts the
|
|
44
|
-
// internal stream to a Fetch API Response instance.
|
|
45
|
-
// Consumers will rely on the Response API when constructing
|
|
46
|
-
// mocked responses.
|
|
47
|
-
message.emit('data', Buffer.from('hello'))
|
|
48
|
-
message.emit('end')
|
|
49
|
-
|
|
50
|
-
expect(response.status).toBe(responseStatus)
|
|
51
|
-
expect(response.body).toBe(null)
|
|
52
|
-
}
|
|
53
|
-
)
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { IncomingHttpHeaders, IncomingMessage } from 'http'
|
|
2
|
-
import { isResponseWithoutBody } from '../../../utils/responseUtils'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Creates a Fetch API `Response` instance from the given
|
|
6
|
-
* `http.IncomingMessage` instance.
|
|
7
|
-
*/
|
|
8
|
-
export function createResponse(message: IncomingMessage): Response {
|
|
9
|
-
const responseBodyOrNull = isResponseWithoutBody(message.statusCode || 200)
|
|
10
|
-
? null
|
|
11
|
-
: new ReadableStream({
|
|
12
|
-
start(controller) {
|
|
13
|
-
message.on('data', (chunk) => controller.enqueue(chunk))
|
|
14
|
-
message.on('end', () => controller.close())
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @todo Should also listen to the "error" on the message
|
|
18
|
-
* and forward it to the controller. Otherwise the stream
|
|
19
|
-
* will pend indefinitely.
|
|
20
|
-
*/
|
|
21
|
-
},
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
return new Response(responseBodyOrNull, {
|
|
25
|
-
status: message.statusCode,
|
|
26
|
-
statusText: message.statusMessage,
|
|
27
|
-
headers: createHeadersFromIncomingHttpHeaders(message.headers),
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function createHeadersFromIncomingHttpHeaders(
|
|
32
|
-
httpHeaders: IncomingHttpHeaders
|
|
33
|
-
): Headers {
|
|
34
|
-
const headers = new Headers()
|
|
35
|
-
|
|
36
|
-
for (const headerName in httpHeaders) {
|
|
37
|
-
const headerValues = httpHeaders[headerName]
|
|
38
|
-
|
|
39
|
-
if (typeof headerValues === 'undefined') {
|
|
40
|
-
continue
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (Array.isArray(headerValues)) {
|
|
44
|
-
headerValues.forEach((headerValue) => {
|
|
45
|
-
headers.append(headerName, headerValue)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
continue
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
headers.set(headerName, headerValues)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return headers
|
|
55
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { it, expect } from 'vitest'
|
|
2
|
-
import { normalizeClientRequestEndArgs } from './normalizeClientRequestEndArgs'
|
|
3
|
-
|
|
4
|
-
it('returns [null, null, cb] given only the callback', () => {
|
|
5
|
-
const callback = () => {}
|
|
6
|
-
expect(normalizeClientRequestEndArgs(callback)).toEqual([
|
|
7
|
-
null,
|
|
8
|
-
null,
|
|
9
|
-
callback,
|
|
10
|
-
])
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('returns [chunk, null, null] given only the chunk', () => {
|
|
14
|
-
expect(normalizeClientRequestEndArgs('chunk')).toEqual(['chunk', null, null])
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('returns [chunk, cb] given the chunk and the callback', () => {
|
|
18
|
-
const callback = () => {}
|
|
19
|
-
expect(normalizeClientRequestEndArgs('chunk', callback)).toEqual([
|
|
20
|
-
'chunk',
|
|
21
|
-
null,
|
|
22
|
-
callback,
|
|
23
|
-
])
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('returns [chunk, encoding] given the chunk with the encoding', () => {
|
|
27
|
-
expect(normalizeClientRequestEndArgs('chunk', 'utf8')).toEqual([
|
|
28
|
-
'chunk',
|
|
29
|
-
'utf8',
|
|
30
|
-
null,
|
|
31
|
-
])
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('returns [chunk, encoding, cb] given all three arguments', () => {
|
|
35
|
-
const callback = () => {}
|
|
36
|
-
expect(normalizeClientRequestEndArgs('chunk', 'utf8', callback)).toEqual([
|
|
37
|
-
'chunk',
|
|
38
|
-
'utf8',
|
|
39
|
-
callback,
|
|
40
|
-
])
|
|
41
|
-
})
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@open-draft/logger'
|
|
2
|
-
|
|
3
|
-
const logger = new Logger('utils getUrlByRequestOptions')
|
|
4
|
-
|
|
5
|
-
export type ClientRequestEndChunk = string | Buffer
|
|
6
|
-
export type ClientRequestEndCallback = () => void
|
|
7
|
-
|
|
8
|
-
type HttpRequestEndArgs =
|
|
9
|
-
| []
|
|
10
|
-
| [ClientRequestEndCallback]
|
|
11
|
-
| [ClientRequestEndChunk, ClientRequestEndCallback?]
|
|
12
|
-
| [ClientRequestEndChunk, BufferEncoding, ClientRequestEndCallback?]
|
|
13
|
-
|
|
14
|
-
type NormalizedHttpRequestEndParams = [
|
|
15
|
-
ClientRequestEndChunk | null,
|
|
16
|
-
BufferEncoding | null,
|
|
17
|
-
ClientRequestEndCallback | null
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Normalizes a list of arguments given to the `ClientRequest.end()`
|
|
22
|
-
* method to always include `chunk`, `encoding`, and `callback`.
|
|
23
|
-
*/
|
|
24
|
-
export function normalizeClientRequestEndArgs(
|
|
25
|
-
...args: HttpRequestEndArgs
|
|
26
|
-
): NormalizedHttpRequestEndParams {
|
|
27
|
-
logger.info('arguments', args)
|
|
28
|
-
const normalizedArgs = new Array(3)
|
|
29
|
-
.fill(null)
|
|
30
|
-
.map((value, index) => args[index] || value)
|
|
31
|
-
|
|
32
|
-
normalizedArgs.sort((a, b) => {
|
|
33
|
-
// If first element is a function, move it rightwards.
|
|
34
|
-
if (typeof a === 'function') {
|
|
35
|
-
return 1
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// If second element is a function, move the first leftwards.
|
|
39
|
-
if (typeof b === 'function') {
|
|
40
|
-
return -1
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// If both elements are strings, preserve their original index.
|
|
44
|
-
if (typeof a === 'string' && typeof b === 'string') {
|
|
45
|
-
return normalizedArgs.indexOf(a) - normalizedArgs.indexOf(b)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return 0
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
logger.info('normalized args', normalizedArgs)
|
|
52
|
-
return normalizedArgs as NormalizedHttpRequestEndParams
|
|
53
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { it, expect } from 'vitest'
|
|
2
|
-
import { normalizeClientRequestWriteArgs } from './normalizeClientRequestWriteArgs'
|
|
3
|
-
|
|
4
|
-
it('returns a triplet of null given no chunk, encoding, or callback', () => {
|
|
5
|
-
expect(
|
|
6
|
-
normalizeClientRequestWriteArgs([
|
|
7
|
-
// @ts-ignore
|
|
8
|
-
undefined,
|
|
9
|
-
undefined,
|
|
10
|
-
undefined,
|
|
11
|
-
])
|
|
12
|
-
).toEqual([undefined, undefined, undefined])
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('returns [chunk, null, null] given only a chunk', () => {
|
|
16
|
-
expect(normalizeClientRequestWriteArgs(['chunk', undefined])).toEqual([
|
|
17
|
-
'chunk',
|
|
18
|
-
undefined,
|
|
19
|
-
undefined,
|
|
20
|
-
])
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
it('returns [chunk, encoding] given only chunk and encoding', () => {
|
|
24
|
-
expect(normalizeClientRequestWriteArgs(['chunk', 'utf8'])).toEqual([
|
|
25
|
-
'chunk',
|
|
26
|
-
'utf8',
|
|
27
|
-
undefined,
|
|
28
|
-
])
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('returns [chunk, encoding, cb] given all three arguments', () => {
|
|
32
|
-
const callbackFn = () => {}
|
|
33
|
-
expect(
|
|
34
|
-
normalizeClientRequestWriteArgs(['chunk', 'utf8', callbackFn])
|
|
35
|
-
).toEqual(['chunk', 'utf8', callbackFn])
|
|
36
|
-
})
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Logger } from '@open-draft/logger'
|
|
2
|
-
|
|
3
|
-
const logger = new Logger('http normalizeWriteArgs')
|
|
4
|
-
|
|
5
|
-
export type ClientRequestWriteCallback = (error?: Error | null) => void
|
|
6
|
-
export type ClientRequestWriteArgs = [
|
|
7
|
-
chunk: string | Buffer,
|
|
8
|
-
encoding?: BufferEncoding | ClientRequestWriteCallback,
|
|
9
|
-
callback?: ClientRequestWriteCallback
|
|
10
|
-
]
|
|
11
|
-
|
|
12
|
-
export type NormalizedClientRequestWriteArgs = [
|
|
13
|
-
chunk: string | Buffer,
|
|
14
|
-
encoding?: BufferEncoding,
|
|
15
|
-
callback?: ClientRequestWriteCallback
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
export function normalizeClientRequestWriteArgs(
|
|
19
|
-
args: ClientRequestWriteArgs
|
|
20
|
-
): NormalizedClientRequestWriteArgs {
|
|
21
|
-
logger.info('normalizing ClientRequest.write arguments...', args)
|
|
22
|
-
|
|
23
|
-
const chunk = args[0]
|
|
24
|
-
const encoding =
|
|
25
|
-
typeof args[1] === 'string' ? (args[1] as BufferEncoding) : undefined
|
|
26
|
-
const callback = typeof args[1] === 'function' ? args[1] : args[2]
|
|
27
|
-
|
|
28
|
-
const writeArgs: NormalizedClientRequestWriteArgs = [
|
|
29
|
-
chunk,
|
|
30
|
-
encoding,
|
|
31
|
-
callback,
|
|
32
|
-
]
|
|
33
|
-
logger.info(
|
|
34
|
-
'successfully normalized ClientRequest.write arguments:',
|
|
35
|
-
writeArgs
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
return writeArgs
|
|
39
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|