mockaton 8.9.0 → 8.10.0
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 +1 -1
- package/package.json +1 -1
- package/src/Api.js +15 -1
- package/src/ApiConstants.js +3 -1
- package/src/Commander.js +12 -2
- package/src/Dashboard.css +29 -15
- package/src/Dashboard.js +35 -8
- package/src/MockBroker.js +3 -4
- package/src/MockDispatcher.js +2 -2
- package/src/Mockaton.test.js +2 -2
- package/src/ProxyRelay.js +5 -5
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ which is handy for setting up tests (see **Commander API** below).
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
##
|
|
33
|
+
## Fallback to your Backend
|
|
34
34
|
Mockaton can fallback to your real backend on routes you don’t have mocks
|
|
35
35
|
for. For that, type your backend address in the **Fallback Backend** field.
|
|
36
36
|
|
package/package.json
CHANGED
package/src/Api.js
CHANGED
|
@@ -34,6 +34,7 @@ export const apiGetRequests = new Map([
|
|
|
34
34
|
[API.fallback, getProxyFallback],
|
|
35
35
|
[API.arEvents, longPollAR_Events],
|
|
36
36
|
[API.comments, listComments],
|
|
37
|
+
[API.globalDelay, getGlobalDelay],
|
|
37
38
|
[API.collectProxied, getCollectProxied]
|
|
38
39
|
])
|
|
39
40
|
|
|
@@ -46,6 +47,7 @@ export const apiPatchRequests = new Map([
|
|
|
46
47
|
[API.cookies, selectCookie],
|
|
47
48
|
[API.fallback, updateProxyFallback],
|
|
48
49
|
[API.bulkSelect, bulkUpdateBrokersByCommentTag],
|
|
50
|
+
[API.globalDelay, setGlobalDelay],
|
|
49
51
|
[API.collectProxied, setCollectProxied]
|
|
50
52
|
])
|
|
51
53
|
|
|
@@ -65,6 +67,7 @@ function serveDashboardAsset(req, response) {
|
|
|
65
67
|
|
|
66
68
|
function listCookies(_, response) { sendJSON(response, cookie.list()) }
|
|
67
69
|
function listComments(_, response) { sendJSON(response, mockBrokersCollection.extractAllComments()) }
|
|
70
|
+
function getGlobalDelay(_, response) { sendJSON(response, config.delay) }
|
|
68
71
|
function listMockBrokers(_, response) { sendJSON(response, mockBrokersCollection.getAll()) }
|
|
69
72
|
function getProxyFallback(_, response) { sendJSON(response, config.proxyFallback) }
|
|
70
73
|
function getIsCorsAllowed(_, response) { sendJSON(response, config.corsAllowed) }
|
|
@@ -78,6 +81,13 @@ function listStaticFiles(req, response) {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
function longPollAR_Events(req, response) {
|
|
84
|
+
// e.g. tab was hidden while new mocks were added or removed
|
|
85
|
+
const clientIsOutOfSync = parseInt(req.headers[DF.lastReceived_nAR], 10) !== countAR_Events()
|
|
86
|
+
if (clientIsOutOfSync) {
|
|
87
|
+
sendJSON(response, countAR_Events())
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
81
91
|
function onAddOrRemoveMock() {
|
|
82
92
|
unsubscribeAR_EventListener(onAddOrRemoveMock)
|
|
83
93
|
sendJSON(response, countAR_Events())
|
|
@@ -130,7 +140,7 @@ async function setRouteIsDelayed(req, response) {
|
|
|
130
140
|
else if (typeof delayed !== 'boolean')
|
|
131
141
|
sendUnprocessableContent(response, `Expected a boolean for "delayed"`) // TESTME
|
|
132
142
|
else {
|
|
133
|
-
broker.
|
|
143
|
+
broker.updateDelayed(body[DF.delayed])
|
|
134
144
|
sendOK(response)
|
|
135
145
|
}
|
|
136
146
|
}
|
|
@@ -181,3 +191,7 @@ async function setCorsAllowed(req, response) {
|
|
|
181
191
|
sendOK(response)
|
|
182
192
|
}
|
|
183
193
|
|
|
194
|
+
async function setGlobalDelay(req, response) { // TESTME
|
|
195
|
+
config.delay = parseInt(await parseJSON(req), 10)
|
|
196
|
+
sendOK(response)
|
|
197
|
+
}
|
package/src/ApiConstants.js
CHANGED
|
@@ -5,6 +5,7 @@ export const API = {
|
|
|
5
5
|
comments: MOUNT + '/comments',
|
|
6
6
|
select: MOUNT + '/select',
|
|
7
7
|
delay: MOUNT + '/delay',
|
|
8
|
+
globalDelay: MOUNT + '/global-delay',
|
|
8
9
|
mocks: MOUNT + '/mocks',
|
|
9
10
|
reset: MOUNT + '/reset',
|
|
10
11
|
cookies: MOUNT + '/cookies',
|
|
@@ -20,7 +21,8 @@ export const DF = { // Dashboard Fields (XHR)
|
|
|
20
21
|
routeMethod: 'route_method',
|
|
21
22
|
routeUrlMask: 'route_url_mask',
|
|
22
23
|
delayed: 'delayed',
|
|
23
|
-
proxied: 'proxied'
|
|
24
|
+
proxied: 'proxied',
|
|
25
|
+
lastReceived_nAR: 'last_received_n_ar'
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
export const DEFAULT_500_COMMENT = '(Mockaton 500)'
|
package/src/Commander.js
CHANGED
|
@@ -77,6 +77,13 @@ export class Commander {
|
|
|
77
77
|
return this.#patch(API.cors, value)
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
getGlobalDelay() {
|
|
81
|
+
return this.#get(API.globalDelay)
|
|
82
|
+
}
|
|
83
|
+
setGlobalDelay(delay) {
|
|
84
|
+
return this.#patch(API.globalDelay, delay)
|
|
85
|
+
}
|
|
86
|
+
|
|
80
87
|
listStaticFiles() {
|
|
81
88
|
return this.#get(API.static)
|
|
82
89
|
}
|
|
@@ -85,9 +92,12 @@ export class Commander {
|
|
|
85
92
|
return this.#patch(API.reset)
|
|
86
93
|
}
|
|
87
94
|
|
|
88
|
-
getAR_EventsCount() {
|
|
95
|
+
getAR_EventsCount(nAR_EventReceived) {
|
|
89
96
|
return fetch(API.arEvents, {
|
|
90
|
-
signal: AbortSignal.timeout(LONG_POLL_SERVER_TIMEOUT + 1000)
|
|
97
|
+
signal: AbortSignal.timeout(LONG_POLL_SERVER_TIMEOUT + 1000),
|
|
98
|
+
headers: {
|
|
99
|
+
[DF.lastReceived_nAR]: nAR_EventReceived
|
|
100
|
+
}
|
|
91
101
|
})
|
|
92
102
|
}
|
|
93
103
|
}
|
package/src/Dashboard.css
CHANGED
|
@@ -112,7 +112,7 @@ select {
|
|
|
112
112
|
border-bottom: 1px solid rgba(127, 127, 127, 0.1);
|
|
113
113
|
background: var(--colorHeaderBackground);
|
|
114
114
|
box-shadow: var(--boxShadow1);
|
|
115
|
-
gap:
|
|
115
|
+
gap: 10px;
|
|
116
116
|
|
|
117
117
|
img {
|
|
118
118
|
width: 130px;
|
|
@@ -129,16 +129,26 @@ select {
|
|
|
129
129
|
color: var(--colorLabel);
|
|
130
130
|
font-size: 11px;
|
|
131
131
|
gap: 4px;
|
|
132
|
+
|
|
133
|
+
svg {
|
|
134
|
+
width: 14px;
|
|
135
|
+
height: 14px;
|
|
136
|
+
fill: var(--colorLabel);
|
|
137
|
+
opacity: 0.6;
|
|
138
|
+
}
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
input[type=url],
|
|
142
|
+
input[type=number],
|
|
135
143
|
select {
|
|
136
144
|
width: 100%;
|
|
137
145
|
height: 28px;
|
|
138
146
|
padding: 4px 8px;
|
|
139
147
|
border-right: 3px solid transparent;
|
|
140
148
|
margin-top: 4px;
|
|
149
|
+
color: var(--colorText);
|
|
141
150
|
font-size: 11px;
|
|
151
|
+
box-shadow: var(--boxShadow1);
|
|
142
152
|
background-color: var(--colorComboBoxHeaderBackground);
|
|
143
153
|
border-radius: var(--radius);
|
|
144
154
|
}
|
|
@@ -147,21 +157,26 @@ select {
|
|
|
147
157
|
background: var(--colorHover);
|
|
148
158
|
}
|
|
149
159
|
|
|
150
|
-
&.
|
|
151
|
-
|
|
152
|
-
|
|
160
|
+
&.GlobalDelayField {
|
|
161
|
+
width: 82px;
|
|
162
|
+
|
|
163
|
+
input[type=number] {
|
|
164
|
+
padding-right: 0;
|
|
165
|
+
}
|
|
153
166
|
|
|
154
167
|
svg {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
opacity: 0.6;
|
|
168
|
+
border: 1px solid var(--colorLabel);
|
|
169
|
+
border-radius: 50%;
|
|
170
|
+
transform: scale(.85);
|
|
159
171
|
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
&.FallbackBackend {
|
|
175
|
+
position: relative;
|
|
176
|
+
width: 210px;
|
|
160
177
|
|
|
161
178
|
input[type=url] {
|
|
162
179
|
padding: 0 6px;
|
|
163
|
-
box-shadow: var(--boxShadow1);
|
|
164
|
-
color: var(--colorText);
|
|
165
180
|
}
|
|
166
181
|
|
|
167
182
|
.SaveProxiedCheckbox {
|
|
@@ -279,8 +294,8 @@ select {
|
|
|
279
294
|
.MockSelector {
|
|
280
295
|
width: 260px;
|
|
281
296
|
height: 30px;
|
|
282
|
-
border: 0;
|
|
283
297
|
padding-right: 5px;
|
|
298
|
+
border: 0;
|
|
284
299
|
text-align: right;
|
|
285
300
|
direction: rtl;
|
|
286
301
|
text-overflow: ellipsis;
|
|
@@ -333,7 +348,7 @@ select {
|
|
|
333
348
|
}
|
|
334
349
|
|
|
335
350
|
&:disabled ~ svg {
|
|
336
|
-
opacity: .
|
|
351
|
+
fill-opacity: 0.4;
|
|
337
352
|
cursor: not-allowed;
|
|
338
353
|
box-shadow: none;
|
|
339
354
|
}
|
|
@@ -350,10 +365,9 @@ select {
|
|
|
350
365
|
}
|
|
351
366
|
|
|
352
367
|
.ProxyToggler {
|
|
353
|
-
margin-left: 4px;
|
|
354
368
|
> svg {
|
|
355
|
-
width:
|
|
356
|
-
padding:
|
|
369
|
+
width: 20px;
|
|
370
|
+
padding: 3px;
|
|
357
371
|
border-color: transparent;
|
|
358
372
|
border-radius: var(--radiusSmall);
|
|
359
373
|
}
|
package/src/Dashboard.js
CHANGED
|
@@ -17,6 +17,7 @@ const Strings = {
|
|
|
17
17
|
cookie: 'Cookie',
|
|
18
18
|
cookie_disabled_title: 'No cookies specified in config.cookies',
|
|
19
19
|
delay: 'Delay',
|
|
20
|
+
delay_ms: 'Delay (ms)',
|
|
20
21
|
empty_response_body: '/* Empty Response Body */',
|
|
21
22
|
fallback_server: 'Fallback Backend',
|
|
22
23
|
fallback_server_placeholder: 'Type Server Address',
|
|
@@ -46,6 +47,7 @@ const CSS = {
|
|
|
46
47
|
ProgressBar: 'ProgressBar',
|
|
47
48
|
ProxyToggler: 'ProxyToggler',
|
|
48
49
|
ResetButton: 'ResetButton',
|
|
50
|
+
GlobalDelayField: 'GlobalDelayField',
|
|
49
51
|
SaveProxiedCheckbox: 'SaveProxiedCheckbox',
|
|
50
52
|
StaticFilesList: 'StaticFilesList',
|
|
51
53
|
|
|
@@ -58,6 +60,10 @@ const CSS = {
|
|
|
58
60
|
const r = createElement
|
|
59
61
|
const mockaton = new Commander(window.location.origin)
|
|
60
62
|
|
|
63
|
+
const PROGRESS_BAR_DELAY = 180
|
|
64
|
+
let globalDelay = 1200
|
|
65
|
+
|
|
66
|
+
|
|
61
67
|
init()
|
|
62
68
|
pollAR_Events() // Add or Remove Mocks from File System
|
|
63
69
|
document.addEventListener('visibilitychange', () => {
|
|
@@ -70,6 +76,7 @@ function init() {
|
|
|
70
76
|
mockaton.listMocks(),
|
|
71
77
|
mockaton.listCookies(),
|
|
72
78
|
mockaton.listComments(),
|
|
79
|
+
mockaton.getGlobalDelay(),
|
|
73
80
|
mockaton.getCollectProxied(),
|
|
74
81
|
mockaton.getProxyFallback(),
|
|
75
82
|
mockaton.listStaticFiles()
|
|
@@ -78,22 +85,24 @@ function init() {
|
|
|
78
85
|
.catch(onError)
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
function App([brokersByMethod, cookies, comments, collectProxied, fallbackAddress, staticFiles]) {
|
|
88
|
+
function App([brokersByMethod, cookies, comments, delay, collectProxied, fallbackAddress, staticFiles]) {
|
|
89
|
+
globalDelay = delay
|
|
82
90
|
return (
|
|
83
91
|
r('div', null,
|
|
84
|
-
r(Header, { cookies, comments, fallbackAddress, collectProxied }),
|
|
92
|
+
r(Header, { cookies, comments, delay, fallbackAddress, collectProxied }),
|
|
85
93
|
r(MockList, { brokersByMethod, canProxy: Boolean(fallbackAddress) }),
|
|
86
94
|
r(StaticFilesList, { staticFiles })))
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
// Header ===============
|
|
90
98
|
|
|
91
|
-
function Header({ cookies, comments, fallbackAddress, collectProxied }) {
|
|
99
|
+
function Header({ cookies, comments, delay, fallbackAddress, collectProxied }) {
|
|
92
100
|
return (
|
|
93
101
|
r('menu', { className: CSS.Header },
|
|
94
102
|
r(Logo),
|
|
95
103
|
r(CookieSelector, { cookies }),
|
|
96
104
|
r(BulkSelector, { comments }),
|
|
105
|
+
r(GlobalDelayField, { delay }),
|
|
97
106
|
r(ProxyFallbackField, { fallbackAddress, collectProxied }),
|
|
98
107
|
r(ResetButton)))
|
|
99
108
|
}
|
|
@@ -153,6 +162,24 @@ function BulkSelector({ comments }) {
|
|
|
153
162
|
r('option', { value }, value)))))
|
|
154
163
|
}
|
|
155
164
|
|
|
165
|
+
function GlobalDelayField({ delay }) {
|
|
166
|
+
function onChange() {
|
|
167
|
+
globalDelay = this.valueAsNumber
|
|
168
|
+
mockaton.setGlobalDelay(globalDelay).catch(onError)
|
|
169
|
+
}
|
|
170
|
+
return (
|
|
171
|
+
r('label', { className: cssClass(CSS.Field, CSS.GlobalDelayField) },
|
|
172
|
+
r('span', null, r(TimerIcon), Strings.delay_ms),
|
|
173
|
+
r('input', {
|
|
174
|
+
type: 'number',
|
|
175
|
+
min: 0,
|
|
176
|
+
step: 100,
|
|
177
|
+
autocomplete: 'none',
|
|
178
|
+
value: delay,
|
|
179
|
+
onChange
|
|
180
|
+
})))
|
|
181
|
+
}
|
|
182
|
+
|
|
156
183
|
function ProxyFallbackField({ fallbackAddress, collectProxied }) {
|
|
157
184
|
function onChange() {
|
|
158
185
|
const saveCheckbox = this.closest(`.${CSS.FallbackBackend}`).querySelector('[type=checkbox]')
|
|
@@ -238,8 +265,8 @@ function SectionByMethod({ method, brokers, canProxy }) {
|
|
|
238
265
|
r('tr', { 'data-method': method, 'data-urlMask': urlMask },
|
|
239
266
|
r('td', null, r(PreviewLink, { method, urlMask })),
|
|
240
267
|
r('td', null, r(MockSelector, { broker })),
|
|
241
|
-
r('td', null, r(DelayRouteToggler, { broker })),
|
|
242
268
|
r('td', null, r(InternalServerErrorToggler, { broker })),
|
|
269
|
+
r('td', null, r(DelayRouteToggler, { broker })),
|
|
243
270
|
r('td', null, r(ProxyToggler, { broker, disabled: !canProxy }))))))
|
|
244
271
|
}
|
|
245
272
|
|
|
@@ -313,7 +340,7 @@ function DelayRouteToggler({ broker }) {
|
|
|
313
340
|
},
|
|
314
341
|
r('input', {
|
|
315
342
|
type: 'checkbox',
|
|
316
|
-
checked:
|
|
343
|
+
checked: broker.currentMock.delayed,
|
|
317
344
|
onChange
|
|
318
345
|
}),
|
|
319
346
|
TimerIcon()))
|
|
@@ -386,7 +413,7 @@ function PayloadViewer() {
|
|
|
386
413
|
function PayloadViewerProgressBar() {
|
|
387
414
|
return (
|
|
388
415
|
r('div', { className: CSS.ProgressBar },
|
|
389
|
-
r('div', { style: { animationDuration: '
|
|
416
|
+
r('div', { style: { animationDuration: globalDelay - PROGRESS_BAR_DELAY + 'ms' } })))
|
|
390
417
|
}
|
|
391
418
|
|
|
392
419
|
function PayloadViewerTitle({ file, status, statusText }) {
|
|
@@ -406,7 +433,7 @@ function PayloadViewerTitleWhenProxied({ mime, status, statusText }) {
|
|
|
406
433
|
}
|
|
407
434
|
|
|
408
435
|
async function previewMock(method, urlMask, href) {
|
|
409
|
-
const timer = setTimeout(renderProgressBar,
|
|
436
|
+
const timer = setTimeout(renderProgressBar, PROGRESS_BAR_DELAY)
|
|
410
437
|
const response = await fetch(href, { method })
|
|
411
438
|
clearTimeout(timer)
|
|
412
439
|
await updatePayloadViewer(method, urlMask, response)
|
|
@@ -512,7 +539,7 @@ async function pollAR_Events() {
|
|
|
512
539
|
return
|
|
513
540
|
try {
|
|
514
541
|
pollAR_Events.isPolling = true
|
|
515
|
-
const response = await mockaton.getAR_EventsCount()
|
|
542
|
+
const response = await mockaton.getAR_EventsCount(pollAR_Events.oldAR_EventsCount)
|
|
516
543
|
if (response.ok) {
|
|
517
544
|
const nAR_Events = await response.json()
|
|
518
545
|
if (pollAR_Events.oldAR_EventsCount !== nAR_Events) { // because it could be < or >
|
package/src/MockBroker.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { config } from './config.js'
|
|
2
1
|
import { includesComment, extractComments, parseFilename } from './Filename.js'
|
|
3
2
|
import { DEFAULT_500_COMMENT, DEFAULT_MOCK_COMMENT } from './ApiConstants.js'
|
|
4
3
|
|
|
@@ -13,7 +12,7 @@ export class MockBroker {
|
|
|
13
12
|
this.mocks = []
|
|
14
13
|
this.currentMock = {
|
|
15
14
|
file: '',
|
|
16
|
-
|
|
15
|
+
delayed: false
|
|
17
16
|
}
|
|
18
17
|
this.register(file)
|
|
19
18
|
}
|
|
@@ -59,7 +58,7 @@ export class MockBroker {
|
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
get file() { return this.currentMock.file }
|
|
62
|
-
get
|
|
61
|
+
get delayed() { return this.currentMock.delayed }
|
|
63
62
|
get proxied() { return !this.currentMock.file }
|
|
64
63
|
get status() { return parseFilename(this.file).status }
|
|
65
64
|
get temp500IsSelected() { return this.#isTemp500(this.file) }
|
|
@@ -83,7 +82,7 @@ export class MockBroker {
|
|
|
83
82
|
|
|
84
83
|
hasMock(file) { return this.mocks.includes(file) }
|
|
85
84
|
updateFile(filename) { this.currentMock.file = filename }
|
|
86
|
-
|
|
85
|
+
updateDelayed(delayed) { this.currentMock.delayed = delayed }
|
|
87
86
|
|
|
88
87
|
updateProxied(proxied) {
|
|
89
88
|
if (proxied)
|
package/src/MockDispatcher.js
CHANGED
|
@@ -14,7 +14,7 @@ export async function dispatchMock(req, response) {
|
|
|
14
14
|
const broker = mockBrokerCollection.getBrokerForUrl(req.method, req.url)
|
|
15
15
|
if (!broker || broker.proxied) {
|
|
16
16
|
if (config.proxyFallback)
|
|
17
|
-
await proxy(req, response)
|
|
17
|
+
await proxy(req, response, Number(Boolean(broker?.delayed)) * config.delay)
|
|
18
18
|
else
|
|
19
19
|
sendNotFound(response)
|
|
20
20
|
return
|
|
@@ -34,7 +34,7 @@ export async function dispatchMock(req, response) {
|
|
|
34
34
|
: await applyPlugins(join(config.mocksDir, broker.file), req, response)
|
|
35
35
|
|
|
36
36
|
response.setHeader('Content-Type', mime)
|
|
37
|
-
setTimeout(() => response.end(body), broker.delay)
|
|
37
|
+
setTimeout(() => response.end(body), Number(broker.delayed) * config.delay)
|
|
38
38
|
}
|
|
39
39
|
catch (error) {
|
|
40
40
|
if (error instanceof BodyReaderError)
|
package/src/Mockaton.test.js
CHANGED
|
@@ -352,7 +352,7 @@ async function testRegistering() {
|
|
|
352
352
|
])
|
|
353
353
|
deepEqual(currentMock, {
|
|
354
354
|
file: fixtureForRegisteringPutA[1],
|
|
355
|
-
|
|
355
|
+
delayed: false
|
|
356
356
|
})
|
|
357
357
|
})
|
|
358
358
|
await it('unregisters selected', async () => {
|
|
@@ -367,7 +367,7 @@ async function testRegistering() {
|
|
|
367
367
|
])
|
|
368
368
|
deepEqual(currentMock, {
|
|
369
369
|
file: fixtureForRegisteringPutB[1],
|
|
370
|
-
|
|
370
|
+
delayed: false
|
|
371
371
|
})
|
|
372
372
|
})
|
|
373
373
|
await it('unregistering the last mock removes broker', async () => {
|
package/src/ProxyRelay.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
|
-
import { existsSync } from 'node:fs'
|
|
3
2
|
import { randomUUID } from 'node:crypto'
|
|
4
|
-
|
|
3
|
+
|
|
5
4
|
import { config } from './config.js'
|
|
6
5
|
import { extFor } from './utils/mime.js'
|
|
7
6
|
import { readBody } from './utils/http-request.js'
|
|
7
|
+
import { write, isFile } from './utils/fs.js'
|
|
8
8
|
import { makeMockFilename } from './Filename.js'
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
export async function proxy(req, response) {
|
|
11
|
+
export async function proxy(req, response, delay) {
|
|
12
12
|
const proxyResponse = await fetch(config.proxyFallback + req.url, {
|
|
13
13
|
method: req.method,
|
|
14
14
|
headers: req.headers,
|
|
@@ -21,12 +21,12 @@ export async function proxy(req, response) {
|
|
|
21
21
|
headers['set-cookie'] = proxyResponse.headers.getSetCookie() // parses multiple into an array
|
|
22
22
|
response.writeHead(proxyResponse.status, headers)
|
|
23
23
|
const body = await proxyResponse.text()
|
|
24
|
-
response.end(body)
|
|
24
|
+
setTimeout(() => response.end(body), delay) // TESTME
|
|
25
25
|
|
|
26
26
|
if (config.collectProxied) {
|
|
27
27
|
const ext = extFor(proxyResponse.headers.get('content-type'))
|
|
28
28
|
let filename = makeMockFilename(req.url, req.method, proxyResponse.status, ext)
|
|
29
|
-
if (
|
|
29
|
+
if (isFile(join(config.mocksDir, filename))) // TESTME
|
|
30
30
|
filename = makeMockFilename(req.url + `(${randomUUID()})`, req.method, proxyResponse.status, ext)
|
|
31
31
|
write(join(config.mocksDir, filename), body)
|
|
32
32
|
}
|