@jsenv/server 14.1.15 → 15.0.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 +4 -4
- package/package.json +4 -4
- package/src/start_server.js +68 -65
package/README.md
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import { startServer } from "@jsenv/server"
|
|
7
7
|
|
|
8
8
|
await startServer({
|
|
9
|
-
protocol: "http",
|
|
10
9
|
port: 8080,
|
|
11
10
|
services: [
|
|
12
11
|
{
|
|
@@ -73,9 +72,10 @@ import { readFileSync } from "node:fs"
|
|
|
73
72
|
import { startServer } from "@jsenv/server"
|
|
74
73
|
|
|
75
74
|
await startServer({
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
https: {
|
|
76
|
+
certificate: readFileSync(new URL("./server.crt", import.meta.url), "utf8"),
|
|
77
|
+
privateKey: readFileSync(new URL("./server.key", import.meta.url), "utf8"),
|
|
78
|
+
},
|
|
79
79
|
allowHttpRequestOnHttps: true,
|
|
80
80
|
services: [
|
|
81
81
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.0.0",
|
|
4
4
|
"description": "Write your Node.js server using pure functions",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@jsenv/abort": "4.2.4",
|
|
38
|
-
"@jsenv/log": "3.3.
|
|
39
|
-
"@jsenv/url-meta": "7.0
|
|
38
|
+
"@jsenv/log": "3.3.4",
|
|
39
|
+
"@jsenv/url-meta": "7.1.0",
|
|
40
40
|
"@jsenv/utils": "2.0.1",
|
|
41
|
-
"ws": "8.
|
|
41
|
+
"ws": "8.13.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@jsenv/fetch": "../fetch/",
|
package/src/start_server.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { isIP } from "node:net"
|
|
2
|
-
import http from "node:http"
|
|
3
2
|
import cluster from "node:cluster"
|
|
4
3
|
import { createDetailedMessage, createLogger } from "@jsenv/log"
|
|
5
4
|
import {
|
|
@@ -50,7 +49,7 @@ export const startServer = async ({
|
|
|
50
49
|
startLog = true,
|
|
51
50
|
serverName = "server",
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
https = false,
|
|
54
53
|
http2 = false,
|
|
55
54
|
http1Allowed = true,
|
|
56
55
|
redirectHttpToHttps,
|
|
@@ -60,8 +59,6 @@ export const startServer = async ({
|
|
|
60
59
|
hostname = "localhost",
|
|
61
60
|
port = 0, // assign a random available port
|
|
62
61
|
portHint,
|
|
63
|
-
privateKey,
|
|
64
|
-
certificate,
|
|
65
62
|
|
|
66
63
|
// when inside a worker, we should not try to stop server on SIGINT
|
|
67
64
|
// otherwise it can create an EPIPE error while primary process tries
|
|
@@ -94,50 +91,60 @@ export const startServer = async ({
|
|
|
94
91
|
// after this delay the underlying stream is destroyed, attempting to read it would throw
|
|
95
92
|
// if used the stream stays opened, it's only if the stream is not read at all that it gets destroyed
|
|
96
93
|
requestBodyLifetime = 60_000 * 2, // 2s
|
|
94
|
+
...rest
|
|
97
95
|
} = {}) => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
throw new Error(`missing certificate for https server`)
|
|
96
|
+
// param validations
|
|
97
|
+
{
|
|
98
|
+
const unexpectedParamNames = Object.keys(rest)
|
|
99
|
+
if (unexpectedParamNames.length > 0) {
|
|
100
|
+
throw new TypeError(
|
|
101
|
+
`${unexpectedParamNames.join(",")}: there is no such param`,
|
|
102
|
+
)
|
|
106
103
|
}
|
|
107
|
-
if (
|
|
108
|
-
|
|
104
|
+
if (https) {
|
|
105
|
+
if (typeof https !== "object") {
|
|
106
|
+
throw new TypeError(`https must be an object, got ${https}`)
|
|
107
|
+
}
|
|
108
|
+
const { certificate, privateKey } = https
|
|
109
|
+
if (!certificate || !privateKey) {
|
|
110
|
+
throw new TypeError(
|
|
111
|
+
`https must be an object with { certificate, privateKey }`,
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (http2 && !https) {
|
|
116
|
+
throw new Error(`http2 needs https`)
|
|
109
117
|
}
|
|
110
118
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
119
|
+
const logger = createLogger({ logLevel })
|
|
120
|
+
// param warnings and normalization
|
|
121
|
+
{
|
|
122
|
+
if (
|
|
123
|
+
redirectHttpToHttps === undefined &&
|
|
124
|
+
https &&
|
|
125
|
+
!allowHttpRequestOnHttps
|
|
126
|
+
) {
|
|
127
|
+
redirectHttpToHttps = true
|
|
128
|
+
}
|
|
129
|
+
if (redirectHttpToHttps && !https) {
|
|
130
|
+
logger.warn(`redirectHttpToHttps ignored because protocol is http`)
|
|
131
|
+
redirectHttpToHttps = false
|
|
132
|
+
}
|
|
133
|
+
if (allowHttpRequestOnHttps && redirectHttpToHttps) {
|
|
134
|
+
logger.warn(
|
|
135
|
+
`redirectHttpToHttps ignored because allowHttpRequestOnHttps is enabled`,
|
|
136
|
+
)
|
|
137
|
+
redirectHttpToHttps = false
|
|
138
|
+
}
|
|
132
139
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
if (allowHttpRequestOnHttps && !https) {
|
|
141
|
+
logger.warn(`allowHttpRequestOnHttps ignored because protocol is http`)
|
|
142
|
+
allowHttpRequestOnHttps = false
|
|
143
|
+
}
|
|
136
144
|
}
|
|
137
145
|
|
|
138
146
|
const server = {}
|
|
139
147
|
const serviceController = createServiceController(services)
|
|
140
|
-
|
|
141
148
|
const processTeardownEvents = {
|
|
142
149
|
SIGHUP: stopOnExit,
|
|
143
150
|
SIGTERM: stopOnExit,
|
|
@@ -164,11 +171,9 @@ export const startServer = async ({
|
|
|
164
171
|
})
|
|
165
172
|
startServerOperation.throwIfAborted()
|
|
166
173
|
nodeServer = await createNodeServer({
|
|
167
|
-
|
|
174
|
+
https,
|
|
168
175
|
redirectHttpToHttps,
|
|
169
176
|
allowHttpRequestOnHttps,
|
|
170
|
-
certificate,
|
|
171
|
-
privateKey,
|
|
172
177
|
http2,
|
|
173
178
|
http1Allowed,
|
|
174
179
|
})
|
|
@@ -180,6 +185,7 @@ export const startServer = async ({
|
|
|
180
185
|
}
|
|
181
186
|
|
|
182
187
|
const createOrigin = (hostname) => {
|
|
188
|
+
const protocol = https ? "https" : "http"
|
|
183
189
|
if (isIP(hostname) === 6) {
|
|
184
190
|
return `${protocol}://[${hostname}]`
|
|
185
191
|
}
|
|
@@ -940,10 +946,9 @@ export const startServer = async ({
|
|
|
940
946
|
const websocketClients = new Set()
|
|
941
947
|
const { WebSocketServer } = await import("ws")
|
|
942
948
|
let websocketServer = new WebSocketServer({ noServer: true })
|
|
943
|
-
const websocketOrigin =
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
: `ws://${hostname}:${port}`
|
|
949
|
+
const websocketOrigin = https
|
|
950
|
+
? `wss://${hostname}:${port}`
|
|
951
|
+
: `ws://${hostname}:${port}`
|
|
947
952
|
server.websocketOrigin = websocketOrigin
|
|
948
953
|
const upgradeCallback = (nodeRequest, socket, head) => {
|
|
949
954
|
websocketServer.handleUpgrade(
|
|
@@ -1020,32 +1025,30 @@ export const startServer = async ({
|
|
|
1020
1025
|
}
|
|
1021
1026
|
|
|
1022
1027
|
const createNodeServer = async ({
|
|
1023
|
-
|
|
1028
|
+
https,
|
|
1024
1029
|
redirectHttpToHttps,
|
|
1025
1030
|
allowHttpRequestOnHttps,
|
|
1026
|
-
certificate,
|
|
1027
|
-
privateKey,
|
|
1028
1031
|
http2,
|
|
1029
1032
|
http1Allowed,
|
|
1030
1033
|
}) => {
|
|
1031
|
-
if (
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1034
|
+
if (https) {
|
|
1035
|
+
const { certificate, privateKey } = https
|
|
1036
|
+
if (redirectHttpToHttps || allowHttpRequestOnHttps) {
|
|
1037
|
+
return createPolyglotServer({
|
|
1038
|
+
certificate,
|
|
1039
|
+
privateKey,
|
|
1040
|
+
http2,
|
|
1041
|
+
http1Allowed,
|
|
1042
|
+
})
|
|
1043
|
+
}
|
|
1044
|
+
const { createServer } = await import("node:https")
|
|
1045
|
+
return createServer({
|
|
1046
|
+
cert: certificate,
|
|
1047
|
+
key: privateKey,
|
|
1041
1048
|
})
|
|
1042
1049
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
return createServer({
|
|
1046
|
-
cert: certificate,
|
|
1047
|
-
key: privateKey,
|
|
1048
|
-
})
|
|
1050
|
+
const { createServer } = await import("node:http")
|
|
1051
|
+
return createServer()
|
|
1049
1052
|
}
|
|
1050
1053
|
|
|
1051
1054
|
const testCanPushStream = (http2Stream) => {
|