@jsenv/server 12.1.0 → 12.2.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 CHANGED
@@ -92,8 +92,8 @@ import { startServer } from "@jsenv/server"
92
92
 
93
93
  await startServer({
94
94
  protocol: "https",
95
- serverCertificate: readFileSyncAsString("./server.crt"),
96
- serverCertificatePrivateKey: readFileSyncAsString("./server.key"),
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/server",
3
- "version": "12.1.0",
3
+ "version": "12.2.0",
4
4
  "description": "Write your Node.js server using pure functions",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -31,15 +31,14 @@
31
31
  "/main.js"
32
32
  ],
33
33
  "scripts": {
34
- "eslint-check": "node ./node_modules/eslint/bin/eslint.js . --ext=.js,.mjs",
35
34
  "importmap-generate": "node ./script/importmap/generate_importmap.mjs",
36
35
  "measure-performances": "node --expose-gc ./script/performance/generate_performance_report.mjs --log",
37
- "test": "node --unhandled-rejections=strict ./script/test/test.mjs",
36
+ "test": "node ./script/test/test.mjs",
38
37
  "test-with-coverage": "npm run test -- --coverage",
39
38
  "generate-html-snapshots": "node ./test/internal_error/generate_html_snapshot_files.mjs",
40
- "prettier-format": "node ./script/prettier/prettier_format.mjs",
41
- "prettier-format-stage": "npm run prettier-format -- --staged",
42
- "prettier-check": "npm run prettier-format -- --dry-run",
39
+ "eslint-check": "node ./node_modules/eslint/bin/eslint.js . --ext=.js,.mjs",
40
+ "prettier-check": "prettier --check .",
41
+ "prettier-write": "prettier --write .",
43
42
  "certificate-authority-install": "node ./script/certificate/certificate_authority_install.mjs",
44
43
  "playwright-install": "npx playwright install-deps && npx playwright install",
45
44
  "prepublishOnly": "node ./script/publish/remove_postinstall.mjs",
@@ -63,7 +62,6 @@
63
62
  "@jsenv/importmap-node-module": "2.7.1",
64
63
  "@jsenv/package-publish": "1.6.2",
65
64
  "@jsenv/performance-impact": "2.2.1",
66
- "@jsenv/prettier-check-project": "5.6.1",
67
65
  "eslint": "8.2.0",
68
66
  "eslint-plugin-import": "2.25.3",
69
67
  "eventsource": "1.1.0",
@@ -11,13 +11,13 @@ import { listenEvent } from "./listenEvent.js"
11
11
  export const createPolyglotServer = async ({
12
12
  http2 = false,
13
13
  http1Allowed = true,
14
- serverCertificate,
15
- serverCertificatePrivateKey,
14
+ certificate,
15
+ privateKey,
16
16
  }) => {
17
17
  const httpServer = http.createServer()
18
18
  const tlsServer = await createSecureServer({
19
- serverCertificate,
20
- serverCertificatePrivateKey,
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
- serverCertificate,
67
- serverCertificatePrivateKey,
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: serverCertificate,
75
- key: serverCertificatePrivateKey,
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: serverCertificate,
83
- key: serverCertificatePrivateKey,
82
+ cert: certificate,
83
+ key: privateKey,
84
84
  })
85
85
  }
86
86
 
@@ -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
- serverCertificatePrivateKey,
51
- serverCertificate,
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 (!serverCertificate) {
78
- throw new Error(`missing serverCertificate for https server`)
77
+ if (!certificate) {
78
+ throw new Error(`missing certificate for https server`)
79
79
  }
80
- if (!serverCertificatePrivateKey) {
81
- throw new Error(`missing serverCertificatePrivateKey for https server`)
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
- serverCertificate,
138
- serverCertificatePrivateKey,
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,7 +465,10 @@ export const startServer = async ({
488
465
  redirectRequest,
489
466
  })
490
467
  if (returnValue) {
491
- requestPlugins.push(returnValue)
468
+ requestPlugins.push({
469
+ pluginName,
470
+ ...returnValue,
471
+ })
492
472
  }
493
473
  }
494
474
  })
@@ -497,10 +477,53 @@ export const startServer = async ({
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
- return pushResponse(
526
+ await pushResponse(
504
527
  { path, method },
505
528
  {
506
529
  requestNode: requestChildNode,
@@ -701,8 +724,8 @@ const createNodeServer = async ({
701
724
  protocol,
702
725
  redirectHttpToHttps,
703
726
  allowHttpRequestOnHttps,
704
- serverCertificate,
705
- serverCertificatePrivateKey,
727
+ certificate,
728
+ privateKey,
706
729
  http2,
707
730
  http1Allowed,
708
731
  }) => {
@@ -712,8 +735,8 @@ const createNodeServer = async ({
712
735
 
713
736
  if (redirectHttpToHttps || allowHttpRequestOnHttps) {
714
737
  return createPolyglotServer({
715
- serverCertificate,
716
- serverCertificatePrivateKey,
738
+ certificate,
739
+ privateKey,
717
740
  http2,
718
741
  http1Allowed,
719
742
  })
@@ -721,8 +744,8 @@ const createNodeServer = async ({
721
744
 
722
745
  const { createServer } = await import("https")
723
746
  return createServer({
724
- cert: serverCertificate,
725
- key: serverCertificatePrivateKey,
747
+ cert: certificate,
748
+ key: privateKey,
726
749
  })
727
750
  }
728
751