@jsenv/server 15.0.2 → 15.0.4
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 +23 -23
- package/package.json +4 -4
- package/src/content_negotiation/pick_accepted_content.js +13 -13
- package/src/content_negotiation/pick_content_encoding.js +25 -25
- package/src/content_negotiation/pick_content_language.js +35 -34
- package/src/content_negotiation/pick_content_type.js +29 -29
- package/src/fetch_filesystem.js +110 -107
- package/src/from_fetch_response.js +6 -6
- package/src/interfacing_with_node/body.js +22 -22
- package/src/interfacing_with_node/observable.js +80 -80
- package/src/interfacing_with_node/observable_from_node_stream.js +35 -35
- package/src/interfacing_with_node/request_factory.js +26 -26
- package/src/interfacing_with_node/write_node_response.js +82 -82
- package/src/internal/colorizeResponseStatus.js +26 -26
- package/src/internal/convertFileSystemErrorToResponseProperties.js +10 -10
- package/src/internal/dns_resolution.js +7 -7
- package/src/internal/etag.js +11 -11
- package/src/internal/filesystem.js +19 -19
- package/src/internal/headersFromObject.js +8 -8
- package/src/internal/headersFromString.js +11 -11
- package/src/internal/headersToObject.js +5 -5
- package/src/internal/headersToString.js +7 -7
- package/src/internal/headers_composition.js +9 -9
- package/src/internal/hostname_parser.js +9 -9
- package/src/internal/listen.js +47 -47
- package/src/internal/listenClientError.js +10 -10
- package/src/internal/listenEvent.js +5 -5
- package/src/internal/listenRequest.js +8 -8
- package/src/internal/listenServerConnectionError.js +19 -19
- package/src/internal/multiple-header.js +50 -50
- package/src/internal/normalizeHeaderName.js +4 -4
- package/src/internal/normalizeHeaderValue.js +2 -2
- package/src/internal/object_composition.js +41 -39
- package/src/internal/response_composition.js +6 -6
- package/src/internal/server-polyglot.js +42 -42
- package/src/internal/server_ips.js +20 -20
- package/src/internal/trackServerPendingConnections.js +23 -23
- package/src/internal/trackServerPendingRequests.js +28 -28
- package/src/main.js +18 -18
- package/src/readRequestBody.js +15 -15
- package/src/serve_directory.js +16 -16
- package/src/server_timing/timing_header.js +24 -24
- package/src/server_timing/timing_measure.js +14 -14
- package/src/service_composition/path_to_regexp.js +173 -168
- package/src/service_composition/routing.js +12 -12
- package/src/service_controller.js +77 -77
- package/src/services/cors/jsenv_service_cors.js +29 -29
- package/src/services/error_handler/jsenv_service_error_handler.js +18 -18
- package/src/services/request_aliases/jsenv_service_request_aliases.js +20 -20
- package/src/services/response_acceptance_check/jsenv_service_response_acceptance_check.js +16 -16
- package/src/sse/sse_room.js +117 -115
- package/src/start_server.js +328 -328
- package/src/stopReasons.js +9 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isIP } from "node:net"
|
|
1
|
+
import { isIP } from "node:net";
|
|
2
2
|
|
|
3
3
|
export const parseHostname = (hostname) => {
|
|
4
4
|
if (hostname === "0.0.0.0") {
|
|
@@ -6,7 +6,7 @@ export const parseHostname = (hostname) => {
|
|
|
6
6
|
type: "ip",
|
|
7
7
|
label: "unspecified",
|
|
8
8
|
version: 4,
|
|
9
|
-
}
|
|
9
|
+
};
|
|
10
10
|
}
|
|
11
11
|
if (
|
|
12
12
|
hostname === "::" ||
|
|
@@ -16,14 +16,14 @@ export const parseHostname = (hostname) => {
|
|
|
16
16
|
type: "ip",
|
|
17
17
|
label: "unspecified",
|
|
18
18
|
version: 6,
|
|
19
|
-
}
|
|
19
|
+
};
|
|
20
20
|
}
|
|
21
21
|
if (hostname === "127.0.0.1") {
|
|
22
22
|
return {
|
|
23
23
|
type: "ip",
|
|
24
24
|
label: "loopback",
|
|
25
25
|
version: 4,
|
|
26
|
-
}
|
|
26
|
+
};
|
|
27
27
|
}
|
|
28
28
|
if (
|
|
29
29
|
hostname === "::1" ||
|
|
@@ -33,16 +33,16 @@ export const parseHostname = (hostname) => {
|
|
|
33
33
|
type: "ip",
|
|
34
34
|
label: "loopback",
|
|
35
35
|
version: 6,
|
|
36
|
-
}
|
|
36
|
+
};
|
|
37
37
|
}
|
|
38
|
-
const ipVersion = isIP(hostname)
|
|
38
|
+
const ipVersion = isIP(hostname);
|
|
39
39
|
if (ipVersion === 0) {
|
|
40
40
|
return {
|
|
41
41
|
type: "hostname",
|
|
42
|
-
}
|
|
42
|
+
};
|
|
43
43
|
}
|
|
44
44
|
return {
|
|
45
45
|
type: "ip",
|
|
46
46
|
version: ipVersion,
|
|
47
|
-
}
|
|
48
|
-
}
|
|
47
|
+
};
|
|
48
|
+
};
|
package/src/internal/listen.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createServer } from "node:net"
|
|
2
|
-
import { Abort } from "@jsenv/abort"
|
|
1
|
+
import { createServer } from "node:net";
|
|
2
|
+
import { Abort } from "@jsenv/abort";
|
|
3
3
|
|
|
4
4
|
const listen = async ({
|
|
5
5
|
signal = new AbortController().signal,
|
|
@@ -8,28 +8,28 @@ const listen = async ({
|
|
|
8
8
|
portHint,
|
|
9
9
|
hostname,
|
|
10
10
|
}) => {
|
|
11
|
-
const listeningOperation = Abort.startOperation()
|
|
11
|
+
const listeningOperation = Abort.startOperation();
|
|
12
12
|
|
|
13
13
|
try {
|
|
14
|
-
listeningOperation.addAbortSignal(signal)
|
|
14
|
+
listeningOperation.addAbortSignal(signal);
|
|
15
15
|
|
|
16
16
|
if (portHint) {
|
|
17
|
-
listeningOperation.throwIfAborted()
|
|
17
|
+
listeningOperation.throwIfAborted();
|
|
18
18
|
port = await findFreePort(portHint, {
|
|
19
19
|
signal: listeningOperation.signal,
|
|
20
20
|
hostname,
|
|
21
|
-
})
|
|
21
|
+
});
|
|
22
22
|
}
|
|
23
|
-
listeningOperation.throwIfAborted()
|
|
24
|
-
port = await startListening({ server, port, hostname })
|
|
25
|
-
listeningOperation.addAbortCallback(() => stopListening(server))
|
|
26
|
-
listeningOperation.throwIfAborted()
|
|
23
|
+
listeningOperation.throwIfAborted();
|
|
24
|
+
port = await startListening({ server, port, hostname });
|
|
25
|
+
listeningOperation.addAbortCallback(() => stopListening(server));
|
|
26
|
+
listeningOperation.throwIfAborted();
|
|
27
27
|
|
|
28
|
-
return port
|
|
28
|
+
return port;
|
|
29
29
|
} finally {
|
|
30
|
-
await listeningOperation.end()
|
|
30
|
+
await listeningOperation.end();
|
|
31
31
|
}
|
|
32
|
-
}
|
|
32
|
+
};
|
|
33
33
|
|
|
34
34
|
export const findFreePort = async (
|
|
35
35
|
initialPort = 1,
|
|
@@ -41,75 +41,75 @@ export const findFreePort = async (
|
|
|
41
41
|
next = (port) => port + 1,
|
|
42
42
|
} = {},
|
|
43
43
|
) => {
|
|
44
|
-
const findFreePortOperation = Abort.startOperation()
|
|
44
|
+
const findFreePortOperation = Abort.startOperation();
|
|
45
45
|
try {
|
|
46
|
-
findFreePortOperation.addAbortSignal(signal)
|
|
47
|
-
findFreePortOperation.throwIfAborted()
|
|
46
|
+
findFreePortOperation.addAbortSignal(signal);
|
|
47
|
+
findFreePortOperation.throwIfAborted();
|
|
48
48
|
|
|
49
49
|
const testUntil = async (port, host) => {
|
|
50
|
-
findFreePortOperation.throwIfAborted()
|
|
51
|
-
const free = await portIsFree(port, host)
|
|
50
|
+
findFreePortOperation.throwIfAborted();
|
|
51
|
+
const free = await portIsFree(port, host);
|
|
52
52
|
if (free) {
|
|
53
|
-
return port
|
|
53
|
+
return port;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
const nextPort = next(port)
|
|
56
|
+
const nextPort = next(port);
|
|
57
57
|
if (nextPort > max) {
|
|
58
58
|
throw new Error(
|
|
59
59
|
`${hostname} has no available port between ${min} and ${max}`,
|
|
60
|
-
)
|
|
60
|
+
);
|
|
61
61
|
}
|
|
62
|
-
return testUntil(nextPort, hostname)
|
|
63
|
-
}
|
|
64
|
-
const freePort = await testUntil(initialPort, hostname)
|
|
65
|
-
return freePort
|
|
62
|
+
return testUntil(nextPort, hostname);
|
|
63
|
+
};
|
|
64
|
+
const freePort = await testUntil(initialPort, hostname);
|
|
65
|
+
return freePort;
|
|
66
66
|
} finally {
|
|
67
|
-
await findFreePortOperation.end()
|
|
67
|
+
await findFreePortOperation.end();
|
|
68
68
|
}
|
|
69
|
-
}
|
|
69
|
+
};
|
|
70
70
|
|
|
71
71
|
const portIsFree = async (port, hostname) => {
|
|
72
|
-
const server = createServer()
|
|
72
|
+
const server = createServer();
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
75
|
await startListening({
|
|
76
76
|
server,
|
|
77
77
|
port,
|
|
78
78
|
hostname,
|
|
79
|
-
})
|
|
79
|
+
});
|
|
80
80
|
} catch (error) {
|
|
81
81
|
if (error && error.code === "EADDRINUSE") {
|
|
82
|
-
return false
|
|
82
|
+
return false;
|
|
83
83
|
}
|
|
84
84
|
if (error && error.code === "EACCES") {
|
|
85
|
-
return false
|
|
85
|
+
return false;
|
|
86
86
|
}
|
|
87
|
-
throw error
|
|
87
|
+
throw error;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
await stopListening(server)
|
|
91
|
-
return true
|
|
92
|
-
}
|
|
90
|
+
await stopListening(server);
|
|
91
|
+
return true;
|
|
92
|
+
};
|
|
93
93
|
|
|
94
94
|
const startListening = ({ server, port, hostname }) => {
|
|
95
95
|
return new Promise((resolve, reject) => {
|
|
96
|
-
server.on("error", reject)
|
|
96
|
+
server.on("error", reject);
|
|
97
97
|
server.on("listening", () => {
|
|
98
98
|
// in case port is 0 (randomly assign an available port)
|
|
99
99
|
// https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback
|
|
100
|
-
resolve(server.address().port)
|
|
101
|
-
})
|
|
102
|
-
server.listen(port, hostname)
|
|
103
|
-
})
|
|
104
|
-
}
|
|
100
|
+
resolve(server.address().port);
|
|
101
|
+
});
|
|
102
|
+
server.listen(port, hostname);
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
105
|
|
|
106
106
|
export const stopListening = (server) => {
|
|
107
107
|
return new Promise((resolve, reject) => {
|
|
108
|
-
server.on("error", reject)
|
|
109
|
-
server.on("close", resolve)
|
|
110
|
-
server.close()
|
|
111
|
-
})
|
|
112
|
-
}
|
|
108
|
+
server.on("error", reject);
|
|
109
|
+
server.on("close", resolve);
|
|
110
|
+
server.close();
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
113
|
|
|
114
114
|
// unit test exports
|
|
115
|
-
export { listen, portIsFree }
|
|
115
|
+
export { listen, portIsFree };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { listenEvent } from "./listenEvent.js"
|
|
1
|
+
import { listenEvent } from "./listenEvent.js";
|
|
2
2
|
|
|
3
3
|
export const listenClientError = (nodeServer, clientErrorCallback) => {
|
|
4
4
|
if (nodeServer._httpServer) {
|
|
@@ -6,22 +6,22 @@ export const listenClientError = (nodeServer, clientErrorCallback) => {
|
|
|
6
6
|
nodeServer,
|
|
7
7
|
"clientError",
|
|
8
8
|
clientErrorCallback,
|
|
9
|
-
)
|
|
9
|
+
);
|
|
10
10
|
const removeHttpClientError = listenEvent(
|
|
11
11
|
nodeServer._httpServer,
|
|
12
12
|
"clientError",
|
|
13
13
|
clientErrorCallback,
|
|
14
|
-
)
|
|
14
|
+
);
|
|
15
15
|
const removeTlsClientError = listenEvent(
|
|
16
16
|
nodeServer._tlsServer,
|
|
17
17
|
"clientError",
|
|
18
18
|
clientErrorCallback,
|
|
19
|
-
)
|
|
19
|
+
);
|
|
20
20
|
return () => {
|
|
21
|
-
removeNetClientError()
|
|
22
|
-
removeHttpClientError()
|
|
23
|
-
removeTlsClientError()
|
|
24
|
-
}
|
|
21
|
+
removeNetClientError();
|
|
22
|
+
removeHttpClientError();
|
|
23
|
+
removeTlsClientError();
|
|
24
|
+
};
|
|
25
25
|
}
|
|
26
|
-
return listenEvent(nodeServer, "clientError", clientErrorCallback)
|
|
27
|
-
}
|
|
26
|
+
return listenEvent(nodeServer, "clientError", clientErrorCallback);
|
|
27
|
+
};
|
|
@@ -5,11 +5,11 @@ export const listenEvent = (
|
|
|
5
5
|
{ once = false } = {},
|
|
6
6
|
) => {
|
|
7
7
|
if (once) {
|
|
8
|
-
objectWithEventEmitter.once(eventName, callback)
|
|
8
|
+
objectWithEventEmitter.once(eventName, callback);
|
|
9
9
|
} else {
|
|
10
|
-
objectWithEventEmitter.addListener(eventName, callback)
|
|
10
|
+
objectWithEventEmitter.addListener(eventName, callback);
|
|
11
11
|
}
|
|
12
12
|
return () => {
|
|
13
|
-
objectWithEventEmitter.removeListener(eventName, callback)
|
|
14
|
-
}
|
|
15
|
-
}
|
|
13
|
+
objectWithEventEmitter.removeListener(eventName, callback);
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { listenEvent } from "./listenEvent.js"
|
|
1
|
+
import { listenEvent } from "./listenEvent.js";
|
|
2
2
|
|
|
3
3
|
export const listenRequest = (nodeServer, requestCallback) => {
|
|
4
4
|
if (nodeServer._httpServer) {
|
|
@@ -6,16 +6,16 @@ export const listenRequest = (nodeServer, requestCallback) => {
|
|
|
6
6
|
nodeServer._httpServer,
|
|
7
7
|
"request",
|
|
8
8
|
requestCallback,
|
|
9
|
-
)
|
|
9
|
+
);
|
|
10
10
|
const removeTlsRequestListener = listenEvent(
|
|
11
11
|
nodeServer._tlsServer,
|
|
12
12
|
"request",
|
|
13
13
|
requestCallback,
|
|
14
|
-
)
|
|
14
|
+
);
|
|
15
15
|
return () => {
|
|
16
|
-
removeHttpRequestListener()
|
|
17
|
-
removeTlsRequestListener()
|
|
18
|
-
}
|
|
16
|
+
removeHttpRequestListener();
|
|
17
|
+
removeTlsRequestListener();
|
|
18
|
+
};
|
|
19
19
|
}
|
|
20
|
-
return listenEvent(nodeServer, "request", requestCallback)
|
|
21
|
-
}
|
|
20
|
+
return listenEvent(nodeServer, "request", requestCallback);
|
|
21
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { listenEvent } from "./listenEvent.js"
|
|
1
|
+
import { listenEvent } from "./listenEvent.js";
|
|
2
2
|
|
|
3
3
|
export const listenServerConnectionError = (
|
|
4
4
|
nodeServer,
|
|
5
5
|
connectionErrorCallback,
|
|
6
6
|
{ ignoreErrorAfterConnectionIsDestroyed = true } = {},
|
|
7
7
|
) => {
|
|
8
|
-
const cleanupSet = new Set()
|
|
8
|
+
const cleanupSet = new Set();
|
|
9
9
|
|
|
10
10
|
const removeConnectionListener = listenEvent(
|
|
11
11
|
nodeServer,
|
|
@@ -16,34 +16,34 @@ export const listenServerConnectionError = (
|
|
|
16
16
|
"error",
|
|
17
17
|
(error) => {
|
|
18
18
|
if (ignoreErrorAfterConnectionIsDestroyed && socket.destroyed) {
|
|
19
|
-
return
|
|
19
|
+
return;
|
|
20
20
|
}
|
|
21
|
-
connectionErrorCallback(error, socket)
|
|
21
|
+
connectionErrorCallback(error, socket);
|
|
22
22
|
},
|
|
23
|
-
)
|
|
23
|
+
);
|
|
24
24
|
const removeOnceSocketCloseListener = listenEvent(
|
|
25
25
|
socket,
|
|
26
26
|
"close",
|
|
27
27
|
() => {
|
|
28
|
-
removeSocketErrorListener()
|
|
29
|
-
cleanupSet.delete(cleanup)
|
|
28
|
+
removeSocketErrorListener();
|
|
29
|
+
cleanupSet.delete(cleanup);
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
once: true,
|
|
33
33
|
},
|
|
34
|
-
)
|
|
34
|
+
);
|
|
35
35
|
const cleanup = () => {
|
|
36
|
-
removeSocketErrorListener()
|
|
37
|
-
removeOnceSocketCloseListener()
|
|
38
|
-
}
|
|
39
|
-
cleanupSet.add(cleanup)
|
|
36
|
+
removeSocketErrorListener();
|
|
37
|
+
removeOnceSocketCloseListener();
|
|
38
|
+
};
|
|
39
|
+
cleanupSet.add(cleanup);
|
|
40
40
|
},
|
|
41
|
-
)
|
|
41
|
+
);
|
|
42
42
|
return () => {
|
|
43
|
-
removeConnectionListener()
|
|
43
|
+
removeConnectionListener();
|
|
44
44
|
cleanupSet.forEach((cleanup) => {
|
|
45
|
-
cleanup()
|
|
46
|
-
})
|
|
47
|
-
cleanupSet.clear()
|
|
48
|
-
}
|
|
49
|
-
}
|
|
45
|
+
cleanup();
|
|
46
|
+
});
|
|
47
|
+
cleanupSet.clear();
|
|
48
|
+
};
|
|
49
|
+
};
|
|
@@ -15,54 +15,54 @@ export const parseMultipleHeader = (
|
|
|
15
15
|
multipleHeaderString,
|
|
16
16
|
{ validateName = () => true, validateProperty = () => true } = {},
|
|
17
17
|
) => {
|
|
18
|
-
const values = multipleHeaderString.split(",")
|
|
19
|
-
const multipleHeader = {}
|
|
18
|
+
const values = multipleHeaderString.split(",");
|
|
19
|
+
const multipleHeader = {};
|
|
20
20
|
values.forEach((value) => {
|
|
21
|
-
const valueTrimmed = value.trim()
|
|
22
|
-
const valueParts = valueTrimmed.split(";")
|
|
23
|
-
const name = valueParts[0]
|
|
24
|
-
const nameValidation = validateName(name)
|
|
21
|
+
const valueTrimmed = value.trim();
|
|
22
|
+
const valueParts = valueTrimmed.split(";");
|
|
23
|
+
const name = valueParts[0];
|
|
24
|
+
const nameValidation = validateName(name);
|
|
25
25
|
if (!nameValidation) {
|
|
26
|
-
return
|
|
26
|
+
return;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const properties = parseHeaderProperties(valueParts.slice(1), {
|
|
30
30
|
validateProperty,
|
|
31
|
-
})
|
|
32
|
-
multipleHeader[name] = properties
|
|
33
|
-
})
|
|
34
|
-
return multipleHeader
|
|
35
|
-
}
|
|
31
|
+
});
|
|
32
|
+
multipleHeader[name] = properties;
|
|
33
|
+
});
|
|
34
|
+
return multipleHeader;
|
|
35
|
+
};
|
|
36
36
|
|
|
37
37
|
const parseHeaderProperties = (headerProperties, { validateProperty }) => {
|
|
38
38
|
const properties = headerProperties.reduce((previous, valuePart) => {
|
|
39
|
-
const [propertyName, propertyValueString] = valuePart.split("=")
|
|
40
|
-
const propertyValue = parseHeaderPropertyValue(propertyValueString)
|
|
41
|
-
const property = { name: propertyName, value: propertyValue }
|
|
42
|
-
const propertyValidation = validateProperty(property)
|
|
39
|
+
const [propertyName, propertyValueString] = valuePart.split("=");
|
|
40
|
+
const propertyValue = parseHeaderPropertyValue(propertyValueString);
|
|
41
|
+
const property = { name: propertyName, value: propertyValue };
|
|
42
|
+
const propertyValidation = validateProperty(property);
|
|
43
43
|
if (!propertyValidation) {
|
|
44
|
-
return previous
|
|
44
|
+
return previous;
|
|
45
45
|
}
|
|
46
46
|
return {
|
|
47
47
|
...previous,
|
|
48
48
|
[property.name]: property.value,
|
|
49
|
-
}
|
|
50
|
-
}, {})
|
|
51
|
-
return properties
|
|
52
|
-
}
|
|
49
|
+
};
|
|
50
|
+
}, {});
|
|
51
|
+
return properties;
|
|
52
|
+
};
|
|
53
53
|
|
|
54
54
|
const parseHeaderPropertyValue = (headerPropertyValueString) => {
|
|
55
|
-
const firstChar = headerPropertyValueString[0]
|
|
55
|
+
const firstChar = headerPropertyValueString[0];
|
|
56
56
|
const lastChar =
|
|
57
|
-
headerPropertyValueString[headerPropertyValueString.length - 1]
|
|
57
|
+
headerPropertyValueString[headerPropertyValueString.length - 1];
|
|
58
58
|
if (firstChar === '"' && lastChar === '"') {
|
|
59
|
-
return headerPropertyValueString.slice(1, -1)
|
|
59
|
+
return headerPropertyValueString.slice(1, -1);
|
|
60
60
|
}
|
|
61
61
|
if (isNaN(headerPropertyValueString)) {
|
|
62
|
-
return headerPropertyValueString
|
|
62
|
+
return headerPropertyValueString;
|
|
63
63
|
}
|
|
64
|
-
return parseFloat(headerPropertyValueString)
|
|
65
|
-
}
|
|
64
|
+
return parseFloat(headerPropertyValueString);
|
|
65
|
+
};
|
|
66
66
|
|
|
67
67
|
export const stringifyMultipleHeader = (
|
|
68
68
|
multipleHeader,
|
|
@@ -70,34 +70,34 @@ export const stringifyMultipleHeader = (
|
|
|
70
70
|
) => {
|
|
71
71
|
return Object.keys(multipleHeader)
|
|
72
72
|
.filter((name) => {
|
|
73
|
-
const headerProperties = multipleHeader[name]
|
|
73
|
+
const headerProperties = multipleHeader[name];
|
|
74
74
|
if (!headerProperties) {
|
|
75
|
-
return false
|
|
75
|
+
return false;
|
|
76
76
|
}
|
|
77
77
|
if (typeof headerProperties !== "object") {
|
|
78
|
-
return false
|
|
78
|
+
return false;
|
|
79
79
|
}
|
|
80
|
-
const nameValidation = validateName(name)
|
|
80
|
+
const nameValidation = validateName(name);
|
|
81
81
|
if (!nameValidation) {
|
|
82
|
-
return false
|
|
82
|
+
return false;
|
|
83
83
|
}
|
|
84
|
-
return true
|
|
84
|
+
return true;
|
|
85
85
|
})
|
|
86
86
|
.map((name) => {
|
|
87
|
-
const headerProperties = multipleHeader[name]
|
|
87
|
+
const headerProperties = multipleHeader[name];
|
|
88
88
|
const headerPropertiesString = stringifyHeaderProperties(
|
|
89
89
|
headerProperties,
|
|
90
90
|
{
|
|
91
91
|
validateProperty,
|
|
92
92
|
},
|
|
93
|
-
)
|
|
93
|
+
);
|
|
94
94
|
if (headerPropertiesString.length) {
|
|
95
|
-
return `${name};${headerPropertiesString}
|
|
95
|
+
return `${name};${headerPropertiesString}`;
|
|
96
96
|
}
|
|
97
|
-
return name
|
|
97
|
+
return name;
|
|
98
98
|
})
|
|
99
|
-
.join(", ")
|
|
100
|
-
}
|
|
99
|
+
.join(", ");
|
|
100
|
+
};
|
|
101
101
|
|
|
102
102
|
const stringifyHeaderProperties = (headerProperties, { validateProperty }) => {
|
|
103
103
|
const headerPropertiesString = Object.keys(headerProperties)
|
|
@@ -105,24 +105,24 @@ const stringifyHeaderProperties = (headerProperties, { validateProperty }) => {
|
|
|
105
105
|
const property = {
|
|
106
106
|
name,
|
|
107
107
|
value: headerProperties[name],
|
|
108
|
-
}
|
|
109
|
-
return property
|
|
108
|
+
};
|
|
109
|
+
return property;
|
|
110
110
|
})
|
|
111
111
|
.filter((property) => {
|
|
112
|
-
const propertyValidation = validateProperty(property)
|
|
112
|
+
const propertyValidation = validateProperty(property);
|
|
113
113
|
if (!propertyValidation) {
|
|
114
|
-
return false
|
|
114
|
+
return false;
|
|
115
115
|
}
|
|
116
|
-
return true
|
|
116
|
+
return true;
|
|
117
117
|
})
|
|
118
118
|
.map(stringifyHeaderProperty)
|
|
119
|
-
.join(";")
|
|
120
|
-
return headerPropertiesString
|
|
121
|
-
}
|
|
119
|
+
.join(";");
|
|
120
|
+
return headerPropertiesString;
|
|
121
|
+
};
|
|
122
122
|
|
|
123
123
|
const stringifyHeaderProperty = ({ name, value }) => {
|
|
124
124
|
if (typeof value === "string") {
|
|
125
|
-
return `${name}="${value}"
|
|
125
|
+
return `${name}="${value}"`;
|
|
126
126
|
}
|
|
127
|
-
return `${name}=${value}
|
|
128
|
-
}
|
|
127
|
+
return `${name}=${value}`;
|
|
128
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export const normalizeHeaderName = (headerName) => {
|
|
2
|
-
headerName = String(headerName)
|
|
2
|
+
headerName = String(headerName);
|
|
3
3
|
if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(headerName)) {
|
|
4
|
-
throw new TypeError("Invalid character in header field name")
|
|
4
|
+
throw new TypeError("Invalid character in header field name");
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
return headerName.toLowerCase()
|
|
8
|
-
}
|
|
7
|
+
return headerName.toLowerCase();
|
|
8
|
+
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export const normalizeHeaderValue = (headerValue) => {
|
|
2
|
-
return String(headerValue)
|
|
3
|
-
}
|
|
2
|
+
return String(headerValue);
|
|
3
|
+
};
|