@jsenv/server 12.1.0 → 12.3.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 +2 -2
- package/main.js +1 -0
- package/package.json +22 -27
- package/src/cors/plugin_cors.js +1 -3
- package/src/from_fetch_response.js +15 -0
- package/src/internal/memoize.js +24 -0
- package/src/internal/populateNodeResponse.js +8 -1
- package/src/internal/server-polyglot.js +10 -10
- package/src/startServer.js +114 -90
package/README.md
CHANGED
|
@@ -92,8 +92,8 @@ import { startServer } from "@jsenv/server"
|
|
|
92
92
|
|
|
93
93
|
await startServer({
|
|
94
94
|
protocol: "https",
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
certificate: readFileSyncAsString("./server.crt"),
|
|
96
|
+
privateKey: readFileSyncAsString("./server.key"),
|
|
97
97
|
allowHttpRequestOnHttps: true,
|
|
98
98
|
requestToResponse: (request) => {
|
|
99
99
|
const clientUsesHttp = request.origin.startsWith("http:")
|
package/main.js
CHANGED
|
@@ -42,6 +42,7 @@ export { pluginContentNegotiationCheck } from "./src/content_negotiation/plugin_
|
|
|
42
42
|
|
|
43
43
|
// others
|
|
44
44
|
export { fetchUrl } from "./src/fetch_url.js"
|
|
45
|
+
export { fromFetchResponse } from "./src/from_fetch_response.js"
|
|
45
46
|
export { composeTwoResponses } from "./src/internal/response_composition.js"
|
|
46
47
|
export { pluginRessourceAliases } from "./src/ressource_aliases/plugin_ressource_aliases.js"
|
|
47
48
|
export { pluginRequestWaitingCheck } from "./src/plugin_request_waiting_check.js"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/server",
|
|
3
|
-
"version": "12.1
|
|
3
|
+
"version": "12.3.1",
|
|
4
4
|
"description": "Write your Node.js server using pure functions",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/jsenv/server"
|
|
14
14
|
},
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": ">=16.
|
|
16
|
+
"node": ">=16.13.0"
|
|
17
17
|
},
|
|
18
18
|
"publishConfig": {
|
|
19
19
|
"access": "public"
|
|
@@ -31,45 +31,40 @@
|
|
|
31
31
|
"/main.js"
|
|
32
32
|
],
|
|
33
33
|
"scripts": {
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"test": "node
|
|
34
|
+
"importmap": "node ./script/importmap/importmap.mjs",
|
|
35
|
+
"eslint": "node ./node_modules/eslint/bin/eslint.js . --ext=.js,.mjs",
|
|
36
|
+
"performance": "node --expose-gc ./script/performance/performance.mjs --log",
|
|
37
|
+
"test": "node ./script/test/test.mjs",
|
|
38
38
|
"test-with-coverage": "npm run test -- --coverage",
|
|
39
39
|
"generate-html-snapshots": "node ./test/internal_error/generate_html_snapshot_files.mjs",
|
|
40
|
-
"prettier
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"certificate-authority-install": "node ./script/certificate/certificate_authority_install.mjs",
|
|
44
|
-
"playwright-install": "npx playwright install-deps && npx playwright install",
|
|
45
|
-
"prepublishOnly": "node ./script/publish/remove_postinstall.mjs",
|
|
46
|
-
"postpublish": "node ./script/publish/restore_postinstall.mjs"
|
|
40
|
+
"prettier": "prettier --write .",
|
|
41
|
+
"certificate-install": "node ./script/certificate/certificate_install.mjs",
|
|
42
|
+
"playwright-install": "npx playwright install-deps && npx playwright install"
|
|
47
43
|
},
|
|
48
44
|
"dependencies": {
|
|
49
|
-
"@jsenv/abort": "4.1.
|
|
45
|
+
"@jsenv/abort": "4.1.2",
|
|
50
46
|
"@jsenv/logger": "4.0.1",
|
|
51
|
-
"@jsenv/url-meta": "6.0.
|
|
47
|
+
"@jsenv/url-meta": "6.0.3",
|
|
52
48
|
"node-fetch": "2.6.2",
|
|
53
49
|
"path-to-regexp": "6.2.0"
|
|
54
50
|
},
|
|
55
51
|
"devDependencies": {
|
|
56
|
-
"@jsenv/assert": "2.
|
|
57
|
-
"@jsenv/core": "
|
|
52
|
+
"@jsenv/assert": "2.4.1",
|
|
53
|
+
"@jsenv/core": "25.1.0",
|
|
58
54
|
"@jsenv/eslint-config": "16.0.9",
|
|
59
|
-
"@jsenv/filesystem": "2.
|
|
55
|
+
"@jsenv/filesystem": "2.6.1",
|
|
60
56
|
"@jsenv/github-release-package": "1.2.3",
|
|
61
57
|
"@jsenv/https-local": "1.0.3",
|
|
62
|
-
"@jsenv/importmap-eslint-resolver": "5.
|
|
63
|
-
"@jsenv/importmap-node-module": "
|
|
58
|
+
"@jsenv/importmap-eslint-resolver": "5.2.2",
|
|
59
|
+
"@jsenv/importmap-node-module": "5.1.0",
|
|
64
60
|
"@jsenv/package-publish": "1.6.2",
|
|
65
61
|
"@jsenv/performance-impact": "2.2.1",
|
|
66
|
-
"
|
|
67
|
-
"eslint": "
|
|
68
|
-
"eslint-plugin-import": "2.25.3",
|
|
62
|
+
"eslint": "8.7.0",
|
|
63
|
+
"eslint-plugin-import": "2.25.4",
|
|
69
64
|
"eventsource": "1.1.0",
|
|
70
|
-
"fastify": "3.
|
|
65
|
+
"fastify": "3.25.3",
|
|
71
66
|
"fastify-static": "4.5.0",
|
|
72
|
-
"playwright": "1.
|
|
73
|
-
"prettier": "2.
|
|
67
|
+
"playwright": "1.17.2",
|
|
68
|
+
"prettier": "2.5.1"
|
|
74
69
|
}
|
|
75
|
-
}
|
|
70
|
+
}
|
package/src/cors/plugin_cors.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { urlToOrigin } from "@jsenv/filesystem"
|
|
2
|
-
|
|
3
1
|
export const jsenvAccessControlAllowedHeaders = ["x-requested-with"]
|
|
4
2
|
|
|
5
3
|
export const jsenvAccessControlAllowedMethods = [
|
|
@@ -107,7 +105,7 @@ const generateAccessControlHeaders = ({
|
|
|
107
105
|
allowedOriginArray.push(headers.origin)
|
|
108
106
|
vary.push("origin")
|
|
109
107
|
} else if ("referer" in headers) {
|
|
110
|
-
allowedOriginArray.push(
|
|
108
|
+
allowedOriginArray.push(new URL(headers.referer).origin)
|
|
111
109
|
vary.push("referer")
|
|
112
110
|
} else {
|
|
113
111
|
allowedOriginArray.push("*")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const fromFetchResponse = (fetchResponse) => {
|
|
2
|
+
const responseHeaders = {}
|
|
3
|
+
const headersToIgnore = ["connection"]
|
|
4
|
+
fetchResponse.headers.forEach((value, name) => {
|
|
5
|
+
if (!headersToIgnore.includes(name)) {
|
|
6
|
+
responseHeaders[name] = value
|
|
7
|
+
}
|
|
8
|
+
})
|
|
9
|
+
return {
|
|
10
|
+
status: fetchResponse.status,
|
|
11
|
+
statusText: fetchResponse.statusText,
|
|
12
|
+
headers: responseHeaders,
|
|
13
|
+
body: fetchResponse.body, // node-fetch assumed
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const memoize = (compute) => {
|
|
2
|
+
let memoized = false
|
|
3
|
+
let memoizedValue
|
|
4
|
+
|
|
5
|
+
const fnWithMemoization = (...args) => {
|
|
6
|
+
if (memoized) {
|
|
7
|
+
return memoizedValue
|
|
8
|
+
}
|
|
9
|
+
// if compute is recursive wait for it to be fully done before storing the value
|
|
10
|
+
// so set memoized boolean after the call
|
|
11
|
+
memoizedValue = compute(...args)
|
|
12
|
+
memoized = true
|
|
13
|
+
return memoizedValue
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
fnWithMemoization.forget = () => {
|
|
17
|
+
const value = memoizedValue
|
|
18
|
+
memoized = false
|
|
19
|
+
memoizedValue = undefined
|
|
20
|
+
return value
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return fnWithMemoization
|
|
24
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import http from "node:http"
|
|
1
2
|
import { Http2ServerResponse } from "node:http2"
|
|
2
3
|
import { raceCallbacks } from "@jsenv/abort"
|
|
3
4
|
|
|
@@ -155,10 +156,13 @@ const writeHead = (responseStream, { status, statusText, headers }) => {
|
|
|
155
156
|
return
|
|
156
157
|
}
|
|
157
158
|
|
|
159
|
+
if (statusText === undefined) {
|
|
160
|
+
statusText = statusTextFromStatus(status)
|
|
161
|
+
}
|
|
162
|
+
|
|
158
163
|
// nodejs strange signature for writeHead force this
|
|
159
164
|
// https://nodejs.org/api/http.html#http_response_writehead_statuscode_statusmessage_headers
|
|
160
165
|
if (
|
|
161
|
-
statusText === undefined ||
|
|
162
166
|
// https://github.com/nodejs/node/blob/79296dc2d02c0b9872bbfcbb89148ea036a546d0/lib/internal/http2/compat.js#L97
|
|
163
167
|
responseIsHttp2ServerResponse
|
|
164
168
|
) {
|
|
@@ -169,6 +173,9 @@ const writeHead = (responseStream, { status, statusText, headers }) => {
|
|
|
169
173
|
responseStream.writeHead(status, statusText, nodeHeaders)
|
|
170
174
|
}
|
|
171
175
|
|
|
176
|
+
const statusTextFromStatus = (status) =>
|
|
177
|
+
http.STATUS_CODES[status] || "not specified"
|
|
178
|
+
|
|
172
179
|
const headersToNodeHeaders = (headers, { ignoreConnectionHeader }) => {
|
|
173
180
|
const nodeHeaders = {}
|
|
174
181
|
|
|
@@ -11,13 +11,13 @@ import { listenEvent } from "./listenEvent.js"
|
|
|
11
11
|
export const createPolyglotServer = async ({
|
|
12
12
|
http2 = false,
|
|
13
13
|
http1Allowed = true,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
certificate,
|
|
15
|
+
privateKey,
|
|
16
16
|
}) => {
|
|
17
17
|
const httpServer = http.createServer()
|
|
18
18
|
const tlsServer = await createSecureServer({
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
certificate,
|
|
20
|
+
privateKey,
|
|
21
21
|
http2,
|
|
22
22
|
http1Allowed,
|
|
23
23
|
})
|
|
@@ -63,24 +63,24 @@ export const createPolyglotServer = async ({
|
|
|
63
63
|
// The async part is just to lazyly import "http2" or "https"
|
|
64
64
|
// so that these module are parsed only if used.
|
|
65
65
|
const createSecureServer = async ({
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
certificate,
|
|
67
|
+
privateKey,
|
|
68
68
|
http2,
|
|
69
69
|
http1Allowed,
|
|
70
70
|
}) => {
|
|
71
71
|
if (http2) {
|
|
72
72
|
const { createSecureServer } = await import("http2")
|
|
73
73
|
return createSecureServer({
|
|
74
|
-
cert:
|
|
75
|
-
key:
|
|
74
|
+
cert: certificate,
|
|
75
|
+
key: privateKey,
|
|
76
76
|
allowHTTP1: http1Allowed,
|
|
77
77
|
})
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
const { createServer } = await import("https")
|
|
81
81
|
return createServer({
|
|
82
|
-
cert:
|
|
83
|
-
key:
|
|
82
|
+
cert: certificate,
|
|
83
|
+
key: privateKey,
|
|
84
84
|
})
|
|
85
85
|
}
|
|
86
86
|
|
package/src/startServer.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import http from "node:http"
|
|
2
2
|
import cluster from "node:cluster"
|
|
3
|
-
import { memoize } from "@jsenv/filesystem"
|
|
4
3
|
import { createDetailedMessage, createLogger } from "@jsenv/logger"
|
|
5
4
|
import {
|
|
6
5
|
Abort,
|
|
@@ -23,6 +22,7 @@ import { listen, stopListening } from "./internal/listen.js"
|
|
|
23
22
|
import { composeTwoResponses } from "./internal/response_composition.js"
|
|
24
23
|
import { listenRequest } from "./internal/listenRequest.js"
|
|
25
24
|
import { listenServerConnectionError } from "./internal/listenServerConnectionError.js"
|
|
25
|
+
import { memoize } from "./internal/memoize.js"
|
|
26
26
|
import { jsenvServerInternalErrorToResponse } from "./jsenvServerInternalErrorToResponse.js"
|
|
27
27
|
import {
|
|
28
28
|
STOP_REASON_INTERNAL_ERROR,
|
|
@@ -47,8 +47,8 @@ export const startServer = async ({
|
|
|
47
47
|
ip = "0.0.0.0", // will it work on windows ? https://github.com/nodejs/node/issues/14900
|
|
48
48
|
port = 0, // assign a random available port
|
|
49
49
|
portHint,
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
privateKey,
|
|
51
|
+
certificate,
|
|
52
52
|
|
|
53
53
|
// when inside a worker, we should not try to stop server on SIGINT
|
|
54
54
|
// otherwise it can create an EPIPE error while primary process tries
|
|
@@ -74,11 +74,11 @@ export const startServer = async ({
|
|
|
74
74
|
throw new Error(`protocol must be http or https, got ${protocol}`)
|
|
75
75
|
}
|
|
76
76
|
if (protocol === "https") {
|
|
77
|
-
if (!
|
|
78
|
-
throw new Error(`missing
|
|
77
|
+
if (!certificate) {
|
|
78
|
+
throw new Error(`missing certificate for https server`)
|
|
79
79
|
}
|
|
80
|
-
if (!
|
|
81
|
-
throw new Error(`missing
|
|
80
|
+
if (!privateKey) {
|
|
81
|
+
throw new Error(`missing privateKey for https server`)
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
if (http2 && protocol !== "https") {
|
|
@@ -134,8 +134,8 @@ export const startServer = async ({
|
|
|
134
134
|
protocol,
|
|
135
135
|
redirectHttpToHttps,
|
|
136
136
|
allowHttpRequestOnHttps,
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
certificate,
|
|
138
|
+
privateKey,
|
|
139
139
|
http2,
|
|
140
140
|
http1Allowed,
|
|
141
141
|
})
|
|
@@ -332,29 +332,6 @@ export const startServer = async ({
|
|
|
332
332
|
const pushResponse = async ({ path, method }, { requestNode }) => {
|
|
333
333
|
const http2Stream = nodeResponse.stream
|
|
334
334
|
|
|
335
|
-
if (typeof path !== "string" || path[0] !== "/") {
|
|
336
|
-
addRequestLog(requestNode, {
|
|
337
|
-
type: "warn",
|
|
338
|
-
value: `pushResponse call ignored because path is invalid (must be a string starting with "/", found ${path})`,
|
|
339
|
-
})
|
|
340
|
-
return
|
|
341
|
-
}
|
|
342
|
-
if (!request.http2) {
|
|
343
|
-
addRequestLog(requestNode, {
|
|
344
|
-
type: "warn",
|
|
345
|
-
value: `pushResponse call ignored because request is not http2`,
|
|
346
|
-
})
|
|
347
|
-
return
|
|
348
|
-
}
|
|
349
|
-
const canPushStream = testCanPushStream(http2Stream)
|
|
350
|
-
if (!canPushStream.can) {
|
|
351
|
-
addRequestLog(requestNode, {
|
|
352
|
-
type: "debug",
|
|
353
|
-
value: `Ignoring call to pushResponse because ${canPushStream.reason}`,
|
|
354
|
-
})
|
|
355
|
-
return
|
|
356
|
-
}
|
|
357
|
-
|
|
358
335
|
// being able to push a stream is nice to have
|
|
359
336
|
// so when it fails it's not critical
|
|
360
337
|
const onPushStreamError = (e) => {
|
|
@@ -488,19 +465,65 @@ export const startServer = async ({
|
|
|
488
465
|
redirectRequest,
|
|
489
466
|
})
|
|
490
467
|
if (returnValue) {
|
|
491
|
-
requestPlugins.push(
|
|
468
|
+
requestPlugins.push({
|
|
469
|
+
pluginName,
|
|
470
|
+
...returnValue,
|
|
471
|
+
})
|
|
492
472
|
}
|
|
493
473
|
}
|
|
494
474
|
})
|
|
495
|
-
|
|
496
|
-
? {
|
|
475
|
+
const result = responseFromShortcircuit
|
|
476
|
+
? { returnValue: responseFromShortcircuit }
|
|
497
477
|
: await generateResponseDescription({
|
|
498
478
|
requestToResponse,
|
|
499
479
|
request,
|
|
500
|
-
pushResponse: ({ path, method }) => {
|
|
480
|
+
pushResponse: async ({ path, method }) => {
|
|
481
|
+
if (typeof path !== "string" || path[0] !== "/") {
|
|
482
|
+
addRequestLog(requestNode, {
|
|
483
|
+
type: "warn",
|
|
484
|
+
value: `response push ignored because path is invalid (must be a string starting with "/", found ${path})`,
|
|
485
|
+
})
|
|
486
|
+
return
|
|
487
|
+
}
|
|
488
|
+
if (!request.http2) {
|
|
489
|
+
addRequestLog(requestNode, {
|
|
490
|
+
type: "warn",
|
|
491
|
+
value: `response push ignored because request is not http2`,
|
|
492
|
+
})
|
|
493
|
+
return
|
|
494
|
+
}
|
|
495
|
+
const canPushStream = testCanPushStream(nodeResponse.stream)
|
|
496
|
+
if (!canPushStream.can) {
|
|
497
|
+
addRequestLog(requestNode, {
|
|
498
|
+
type: "debug",
|
|
499
|
+
value: `response push ignored because ${canPushStream.reason}`,
|
|
500
|
+
})
|
|
501
|
+
return
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
let prevented = false
|
|
505
|
+
const prevent = () => {
|
|
506
|
+
prevented = true
|
|
507
|
+
}
|
|
508
|
+
const preventedByPlugin = requestPlugins.find((requestPlugin) => {
|
|
509
|
+
const { onPushResponse } = requestPlugin
|
|
510
|
+
if (!onPushResponse) {
|
|
511
|
+
return false
|
|
512
|
+
}
|
|
513
|
+
onPushResponse({ path, method }, { prevent })
|
|
514
|
+
return prevented
|
|
515
|
+
})
|
|
516
|
+
if (prevented) {
|
|
517
|
+
addRequestLog(requestNode, {
|
|
518
|
+
type: "debug",
|
|
519
|
+
value: `response push prevented by "${preventedByPlugin.pluginName}" plugin`,
|
|
520
|
+
})
|
|
521
|
+
return
|
|
522
|
+
}
|
|
523
|
+
|
|
501
524
|
const requestChildNode = { logs: [], children: [] }
|
|
502
525
|
requestNode.children.push(requestChildNode)
|
|
503
|
-
|
|
526
|
+
await pushResponse(
|
|
504
527
|
{ path, method },
|
|
505
528
|
{
|
|
506
529
|
requestNode: requestChildNode,
|
|
@@ -510,65 +533,72 @@ export const startServer = async ({
|
|
|
510
533
|
},
|
|
511
534
|
})
|
|
512
535
|
|
|
536
|
+
const { aborted } = result
|
|
513
537
|
if (aborted) {
|
|
514
538
|
return ABORTED_RESPONSE_PROPERTIES
|
|
515
539
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
{
|
|
536
|
-
status: 500,
|
|
537
|
-
statusText: statusToStatusText(500),
|
|
538
|
-
headers: {
|
|
539
|
-
// ensure error are not cached
|
|
540
|
-
"cache-control": "no-store",
|
|
541
|
-
"content-type": "text/plain",
|
|
540
|
+
const readResponseProperties = async () => {
|
|
541
|
+
const { error } = result
|
|
542
|
+
// internal error, create 500 response
|
|
543
|
+
if (error) {
|
|
544
|
+
if (
|
|
545
|
+
// stopOnInternalError stops server only if requestToResponse generated
|
|
546
|
+
// a non controlled error (internal error).
|
|
547
|
+
// if requestToResponse gracefully produced a 500 response (it did not throw)
|
|
548
|
+
// then we can assume we are still in control of what we are doing
|
|
549
|
+
stopOnInternalError
|
|
550
|
+
) {
|
|
551
|
+
// il faudrais pouvoir stop que les autres response ?
|
|
552
|
+
stop(STOP_REASON_INTERNAL_ERROR)
|
|
553
|
+
}
|
|
554
|
+
const propertiesFromError = await serverInternalErrorToResponse(
|
|
555
|
+
error,
|
|
556
|
+
{
|
|
557
|
+
request,
|
|
558
|
+
sendServerInternalErrorDetails,
|
|
542
559
|
},
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
560
|
+
)
|
|
561
|
+
addRequestLog(requestNode, {
|
|
562
|
+
type: "error",
|
|
563
|
+
value: createDetailedMessage(
|
|
564
|
+
`internal error while handling request`,
|
|
565
|
+
{
|
|
566
|
+
"error stack": error.stack,
|
|
567
|
+
},
|
|
568
|
+
),
|
|
569
|
+
})
|
|
570
|
+
return composeTwoResponses(
|
|
550
571
|
{
|
|
551
|
-
|
|
572
|
+
status: 500,
|
|
573
|
+
statusText: "Internal Server Error",
|
|
574
|
+
headers: {
|
|
575
|
+
// ensure error are not cached
|
|
576
|
+
"cache-control": "no-store",
|
|
577
|
+
"content-type": "text/plain",
|
|
578
|
+
},
|
|
552
579
|
},
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
580
|
+
propertiesFromError,
|
|
581
|
+
)
|
|
582
|
+
}
|
|
583
|
+
|
|
556
584
|
const {
|
|
557
585
|
status = 501,
|
|
558
|
-
statusText
|
|
586
|
+
statusText,
|
|
559
587
|
headers = {},
|
|
560
588
|
body,
|
|
561
589
|
...rest
|
|
562
|
-
} =
|
|
563
|
-
responseProperties = {
|
|
590
|
+
} = result.returnValue || {}
|
|
591
|
+
const responseProperties = {
|
|
564
592
|
status,
|
|
565
593
|
statusText,
|
|
566
594
|
headers,
|
|
567
595
|
body,
|
|
568
596
|
...rest,
|
|
569
597
|
}
|
|
598
|
+
return responseProperties
|
|
570
599
|
}
|
|
571
600
|
|
|
601
|
+
let responseProperties = await readResponseProperties()
|
|
572
602
|
// call every plugin "onResponse" hook
|
|
573
603
|
requestPlugins.forEach((requestPlugin) => {
|
|
574
604
|
const { onResponse } = requestPlugin
|
|
@@ -582,7 +612,6 @@ export const startServer = async ({
|
|
|
582
612
|
}
|
|
583
613
|
}
|
|
584
614
|
})
|
|
585
|
-
|
|
586
615
|
if (
|
|
587
616
|
request.method !== "HEAD" &&
|
|
588
617
|
responseProperties.headers["content-length"] > 0 &&
|
|
@@ -593,7 +622,6 @@ export const startServer = async ({
|
|
|
593
622
|
value: `content-length header is ${responseProperties.headers["content-length"]} but body is empty`,
|
|
594
623
|
})
|
|
595
624
|
}
|
|
596
|
-
|
|
597
625
|
return responseProperties
|
|
598
626
|
}
|
|
599
627
|
|
|
@@ -701,8 +729,8 @@ const createNodeServer = async ({
|
|
|
701
729
|
protocol,
|
|
702
730
|
redirectHttpToHttps,
|
|
703
731
|
allowHttpRequestOnHttps,
|
|
704
|
-
|
|
705
|
-
|
|
732
|
+
certificate,
|
|
733
|
+
privateKey,
|
|
706
734
|
http2,
|
|
707
735
|
http1Allowed,
|
|
708
736
|
}) => {
|
|
@@ -712,8 +740,8 @@ const createNodeServer = async ({
|
|
|
712
740
|
|
|
713
741
|
if (redirectHttpToHttps || allowHttpRequestOnHttps) {
|
|
714
742
|
return createPolyglotServer({
|
|
715
|
-
|
|
716
|
-
|
|
743
|
+
certificate,
|
|
744
|
+
privateKey,
|
|
717
745
|
http2,
|
|
718
746
|
http1Allowed,
|
|
719
747
|
})
|
|
@@ -721,8 +749,8 @@ const createNodeServer = async ({
|
|
|
721
749
|
|
|
722
750
|
const { createServer } = await import("https")
|
|
723
751
|
return createServer({
|
|
724
|
-
cert:
|
|
725
|
-
key:
|
|
752
|
+
cert: certificate,
|
|
753
|
+
key: privateKey,
|
|
726
754
|
})
|
|
727
755
|
}
|
|
728
756
|
|
|
@@ -736,7 +764,7 @@ const generateResponseDescription = async ({
|
|
|
736
764
|
pushResponse,
|
|
737
765
|
})
|
|
738
766
|
return {
|
|
739
|
-
|
|
767
|
+
returnValue,
|
|
740
768
|
}
|
|
741
769
|
} catch (error) {
|
|
742
770
|
if (error.name === "AbortError" && request.signal.aborted) {
|
|
@@ -749,10 +777,6 @@ const generateResponseDescription = async ({
|
|
|
749
777
|
}
|
|
750
778
|
}
|
|
751
779
|
}
|
|
752
|
-
|
|
753
|
-
const statusToStatusText = (status) =>
|
|
754
|
-
http.STATUS_CODES[status] || "not specified"
|
|
755
|
-
|
|
756
780
|
const testCanPushStream = (http2Stream) => {
|
|
757
781
|
if (!http2Stream.pushAllowed) {
|
|
758
782
|
return {
|