@modern-js/prod-server 1.22.1 → 2.0.0-alpha.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/CHANGELOG.md +271 -17
- package/dist/js/modern/constants.js +32 -27
- package/dist/js/modern/index.js +11 -7
- package/dist/js/modern/libs/context/context.js +54 -132
- package/dist/js/modern/libs/context/index.js +5 -2
- package/dist/js/modern/libs/hook-api/index.js +134 -0
- package/dist/js/modern/libs/hook-api/route.js +13 -37
- package/dist/js/modern/libs/hook-api/template.js +41 -32
- package/dist/js/modern/libs/loadConfig.js +46 -32
- package/dist/js/modern/libs/metrics.js +6 -7
- package/dist/js/modern/libs/proxy.js +70 -44
- package/dist/js/modern/libs/render/cache/__tests__/cache.fun.test.js +112 -68
- package/dist/js/modern/libs/render/cache/__tests__/cache.test.js +246 -225
- package/dist/js/modern/libs/render/cache/__tests__/cacheable.js +43 -49
- package/dist/js/modern/libs/render/cache/__tests__/error-configuration.js +36 -34
- package/dist/js/modern/libs/render/cache/__tests__/matched-cache.js +83 -113
- package/dist/js/modern/libs/render/cache/index.js +93 -50
- package/dist/js/modern/libs/render/cache/page-caches/index.js +31 -8
- package/dist/js/modern/libs/render/cache/page-caches/lru.js +6 -16
- package/dist/js/modern/libs/render/cache/spr.js +133 -167
- package/dist/js/modern/libs/render/cache/type.js +0 -1
- package/dist/js/modern/libs/render/cache/util.js +71 -45
- package/dist/js/modern/libs/render/index.js +76 -61
- package/dist/js/modern/libs/render/measure.js +42 -34
- package/dist/js/modern/libs/render/reader.js +68 -76
- package/dist/js/modern/libs/render/ssr.js +63 -33
- package/dist/js/modern/libs/render/static.js +51 -37
- package/dist/js/modern/libs/render/type.js +9 -7
- package/dist/js/modern/libs/route/index.js +12 -30
- package/dist/js/modern/libs/route/matcher.js +28 -50
- package/dist/js/modern/libs/route/route.js +9 -31
- package/dist/js/modern/libs/serve-file.js +40 -20
- package/dist/js/modern/server/index.js +152 -168
- package/dist/js/modern/server/modern-server-split.js +44 -60
- package/dist/js/modern/server/modern-server.js +416 -526
- package/dist/js/modern/type.js +0 -1
- package/dist/js/modern/utils.js +62 -58
- package/dist/js/modern/worker-server.js +54 -0
- package/dist/js/node/constants.js +53 -32
- package/dist/js/node/index.js +37 -67
- package/dist/js/node/libs/context/context.js +84 -150
- package/dist/js/node/libs/context/index.js +28 -16
- package/dist/js/node/libs/hook-api/index.js +164 -0
- package/dist/js/node/libs/hook-api/route.js +35 -45
- package/dist/js/node/libs/hook-api/template.js +64 -40
- package/dist/js/node/libs/loadConfig.js +74 -55
- package/dist/js/node/libs/metrics.js +28 -12
- package/dist/js/node/libs/proxy.js +90 -55
- package/dist/js/node/libs/render/cache/__tests__/cache.fun.test.js +99 -61
- package/dist/js/node/libs/render/cache/__tests__/cache.test.js +147 -140
- package/dist/js/node/libs/render/cache/__tests__/cacheable.js +65 -55
- package/dist/js/node/libs/render/cache/__tests__/error-configuration.js +58 -40
- package/dist/js/node/libs/render/cache/__tests__/matched-cache.js +105 -119
- package/dist/js/node/libs/render/cache/index.js +115 -65
- package/dist/js/node/libs/render/cache/page-caches/index.js +54 -16
- package/dist/js/node/libs/render/cache/page-caches/lru.js +33 -26
- package/dist/js/node/libs/render/cache/spr.js +161 -188
- package/dist/js/node/libs/render/cache/type.js +15 -5
- package/dist/js/node/libs/render/cache/util.js +99 -63
- package/dist/js/node/libs/render/index.js +106 -87
- package/dist/js/node/libs/render/measure.js +61 -44
- package/dist/js/node/libs/render/reader.js +98 -100
- package/dist/js/node/libs/render/ssr.js +92 -58
- package/dist/js/node/libs/render/static.js +80 -53
- package/dist/js/node/libs/render/type.js +31 -13
- package/dist/js/node/libs/route/index.js +35 -44
- package/dist/js/node/libs/route/matcher.js +48 -65
- package/dist/js/node/libs/route/route.js +29 -37
- package/dist/js/node/libs/serve-file.js +74 -37
- package/dist/js/node/server/index.js +170 -203
- package/dist/js/node/server/modern-server-split.js +70 -73
- package/dist/js/node/server/modern-server.js +432 -577
- package/dist/js/node/type.js +15 -3
- package/dist/js/node/utils.js +87 -93
- package/dist/js/node/worker-server.js +77 -0
- package/dist/js/treeshaking/constants.js +29 -0
- package/dist/js/treeshaking/index.js +13 -0
- package/dist/js/treeshaking/libs/context/context.js +274 -0
- package/dist/js/treeshaking/libs/context/index.js +5 -0
- package/dist/js/treeshaking/libs/hook-api/index.js +281 -0
- package/dist/js/treeshaking/libs/hook-api/route.js +68 -0
- package/dist/js/treeshaking/libs/hook-api/template.js +127 -0
- package/dist/js/treeshaking/libs/loadConfig.js +82 -0
- package/dist/js/treeshaking/libs/metrics.js +6 -0
- package/dist/js/treeshaking/libs/proxy.js +244 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cache.fun.test.js +291 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cache.test.js +781 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/cacheable.js +67 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/error-configuration.js +45 -0
- package/dist/js/treeshaking/libs/render/cache/__tests__/matched-cache.js +147 -0
- package/dist/js/treeshaking/libs/render/cache/index.js +346 -0
- package/dist/js/treeshaking/libs/render/cache/page-caches/index.js +154 -0
- package/dist/js/treeshaking/libs/render/cache/page-caches/lru.js +84 -0
- package/dist/js/treeshaking/libs/render/cache/spr.js +492 -0
- package/dist/js/treeshaking/libs/render/cache/type.js +1 -0
- package/dist/js/treeshaking/libs/render/cache/util.js +280 -0
- package/dist/js/treeshaking/libs/render/index.js +233 -0
- package/dist/js/treeshaking/libs/render/measure.js +146 -0
- package/dist/js/treeshaking/libs/render/reader.js +339 -0
- package/dist/js/treeshaking/libs/render/ssr.js +223 -0
- package/dist/js/treeshaking/libs/render/static.js +216 -0
- package/dist/js/treeshaking/libs/render/type.js +7 -0
- package/dist/js/treeshaking/libs/route/index.js +130 -0
- package/dist/js/treeshaking/libs/route/matcher.js +138 -0
- package/dist/js/treeshaking/libs/route/route.js +40 -0
- package/dist/js/treeshaking/libs/serve-file.js +184 -0
- package/dist/js/treeshaking/server/index.js +505 -0
- package/dist/js/treeshaking/server/modern-server-split.js +360 -0
- package/dist/js/treeshaking/server/modern-server.js +1083 -0
- package/dist/js/treeshaking/type.js +1 -0
- package/dist/js/treeshaking/utils.js +147 -0
- package/dist/js/treeshaking/worker-server.js +177 -0
- package/dist/types/libs/context/context.d.ts +1 -1
- package/dist/types/libs/hook-api/index.d.ts +5 -0
- package/dist/types/libs/hook-api/route.d.ts +9 -14
- package/dist/types/libs/hook-api/template.d.ts +19 -9
- package/dist/types/libs/render/cache/index.d.ts +4 -2
- package/dist/types/libs/render/type.d.ts +3 -1
- package/dist/types/libs/route/route.d.ts +0 -1
- package/dist/types/libs/serve-file.d.ts +2 -1
- package/dist/types/server/index.d.ts +2 -0
- package/dist/types/server/modern-server.d.ts +11 -11
- package/dist/types/type.d.ts +8 -10
- package/dist/types/utils.d.ts +3 -4
- package/dist/types/worker-server.d.ts +15 -0
- package/package.json +31 -45
- package/dist/js/modern/libs/render/modern/browser-list.js +0 -7
- package/dist/js/modern/libs/render/modern/index.js +0 -48
- package/dist/js/node/libs/render/modern/browser-list.js +0 -14
- package/dist/js/node/libs/render/modern/index.js +0 -64
- package/dist/types/libs/render/modern/browser-list.d.ts +0 -1
- package/dist/types/libs/render/modern/index.d.ts +0 -3
|
@@ -1,38 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
var __objRest = (source, exclude) => {
|
|
18
|
+
var target = {};
|
|
19
|
+
for (var prop in source)
|
|
20
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
21
|
+
target[prop] = source[prop];
|
|
22
|
+
if (source != null && __getOwnPropSymbols)
|
|
23
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
24
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
25
|
+
target[prop] = source[prop];
|
|
26
|
+
}
|
|
27
|
+
return target;
|
|
28
|
+
};
|
|
29
|
+
var __async = (__this, __arguments, generator) => {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
var fulfilled = (value) => {
|
|
32
|
+
try {
|
|
33
|
+
step(generator.next(value));
|
|
34
|
+
} catch (e) {
|
|
35
|
+
reject(e);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var rejected = (value) => {
|
|
39
|
+
try {
|
|
40
|
+
step(generator.throw(value));
|
|
41
|
+
} catch (e) {
|
|
42
|
+
reject(e);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
46
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
import { createServer } from "http";
|
|
50
|
+
import path from "path";
|
|
51
|
+
import { fs, isPromise, mime, ROUTE_SPEC_FILE } from "@modern-js/utils";
|
|
52
|
+
import {
|
|
53
|
+
RouteMatchManager
|
|
54
|
+
} from "../libs/route";
|
|
21
55
|
import { createRenderHandler } from "../libs/render";
|
|
22
|
-
import {
|
|
23
|
-
|
|
56
|
+
import {
|
|
57
|
+
createStaticFileHandler,
|
|
58
|
+
faviconFallbackHandler
|
|
59
|
+
} from "../libs/serve-file";
|
|
60
|
+
import {
|
|
61
|
+
createErrorDocument,
|
|
62
|
+
createMiddlewareCollecter,
|
|
63
|
+
getStaticReg,
|
|
64
|
+
mergeExtension,
|
|
65
|
+
noop,
|
|
66
|
+
debug,
|
|
67
|
+
isRedirect
|
|
68
|
+
} from "../utils";
|
|
24
69
|
import * as reader from "../libs/render/reader";
|
|
25
70
|
import { createProxyHandler } from "../libs/proxy";
|
|
26
71
|
import { createContext } from "../libs/context";
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
72
|
+
import { templateInjectableStream } from "../libs/hook-api/template";
|
|
73
|
+
import {
|
|
74
|
+
AGGRED_DIR,
|
|
75
|
+
ERROR_DIGEST,
|
|
76
|
+
ERROR_PAGE_TEXT,
|
|
77
|
+
RUN_MODE
|
|
78
|
+
} from "../constants";
|
|
79
|
+
import {
|
|
80
|
+
createAfterMatchContext,
|
|
81
|
+
createAfterRenderContext,
|
|
82
|
+
createMiddlewareContext
|
|
83
|
+
} from "../libs/hook-api";
|
|
84
|
+
const API_DIR = "./api";
|
|
85
|
+
const SERVER_DIR = "./server";
|
|
86
|
+
class ModernServer {
|
|
36
87
|
constructor({
|
|
37
88
|
pwd,
|
|
38
89
|
config,
|
|
@@ -43,616 +94,455 @@ export class ModernServer {
|
|
|
43
94
|
runMode,
|
|
44
95
|
proxyTarget
|
|
45
96
|
}) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
_defineProperty(this, "router", void 0);
|
|
55
|
-
|
|
56
|
-
_defineProperty(this, "conf", void 0);
|
|
57
|
-
|
|
58
|
-
_defineProperty(this, "handlers", []);
|
|
59
|
-
|
|
60
|
-
_defineProperty(this, "presetRoutes", void 0);
|
|
61
|
-
|
|
62
|
-
_defineProperty(this, "runner", void 0);
|
|
63
|
-
|
|
64
|
-
_defineProperty(this, "logger", void 0);
|
|
65
|
-
|
|
66
|
-
_defineProperty(this, "metrics", void 0);
|
|
67
|
-
|
|
68
|
-
_defineProperty(this, "runMode", void 0);
|
|
69
|
-
|
|
70
|
-
_defineProperty(this, "reader", reader);
|
|
71
|
-
|
|
72
|
-
_defineProperty(this, "proxyTarget", void 0);
|
|
73
|
-
|
|
74
|
-
_defineProperty(this, "staticFileHandler", void 0);
|
|
75
|
-
|
|
76
|
-
_defineProperty(this, "routeRenderHandler", void 0);
|
|
77
|
-
|
|
78
|
-
_defineProperty(this, "frameWebHandler", null);
|
|
79
|
-
|
|
80
|
-
_defineProperty(this, "frameAPIHandler", null);
|
|
81
|
-
|
|
82
|
-
_defineProperty(this, "proxyHandler", null);
|
|
83
|
-
|
|
84
|
-
_defineProperty(this, "_handler", void 0);
|
|
85
|
-
|
|
86
|
-
_defineProperty(this, "staticGenerate", void 0);
|
|
87
|
-
|
|
88
|
-
require('ignore-styles');
|
|
89
|
-
|
|
97
|
+
this.handlers = [];
|
|
98
|
+
this.reader = reader;
|
|
99
|
+
this.beforeRouteHandler = null;
|
|
100
|
+
this.frameWebHandler = null;
|
|
101
|
+
this.frameAPIHandler = null;
|
|
102
|
+
this.proxyHandler = null;
|
|
103
|
+
require("ignore-styles");
|
|
90
104
|
this.pwd = pwd;
|
|
91
|
-
this.distDir = path.join(pwd,
|
|
105
|
+
this.distDir = path.join(pwd, config.output.path || "dist");
|
|
92
106
|
this.workDir = this.distDir;
|
|
93
107
|
this.conf = config;
|
|
94
|
-
debug(
|
|
108
|
+
debug("server conf", this.conf);
|
|
95
109
|
this.logger = logger;
|
|
96
110
|
this.metrics = metrics;
|
|
97
111
|
this.router = new RouteMatchManager();
|
|
98
112
|
this.presetRoutes = routes;
|
|
99
113
|
this.proxyTarget = proxyTarget;
|
|
100
114
|
this.staticGenerate = staticGenerate || false;
|
|
101
|
-
this.runMode = runMode || RUN_MODE.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this.
|
|
121
|
-
|
|
115
|
+
this.runMode = runMode || RUN_MODE.FULL;
|
|
116
|
+
}
|
|
117
|
+
onInit(runner, app) {
|
|
118
|
+
return __async(this, null, function* () {
|
|
119
|
+
var _a;
|
|
120
|
+
this.runner = runner;
|
|
121
|
+
const { distDir, staticGenerate, conf } = this;
|
|
122
|
+
debug("final server conf", this.conf);
|
|
123
|
+
this.proxyHandler = createProxyHandler((_a = conf.bff) == null ? void 0 : _a.proxy);
|
|
124
|
+
if (this.proxyHandler) {
|
|
125
|
+
this.proxyHandler.forEach((handler) => {
|
|
126
|
+
this.addHandler(handler);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
this.reader.init();
|
|
130
|
+
app.on("close", () => {
|
|
131
|
+
this.reader.close();
|
|
132
|
+
});
|
|
133
|
+
const usageRoutes = this.filterRoutes(this.getRoutes());
|
|
134
|
+
this.router.reset(usageRoutes);
|
|
135
|
+
this.warmupSSRBundle();
|
|
136
|
+
yield this.prepareFrameHandler();
|
|
137
|
+
yield this.prepareBeforeRouteHandler(usageRoutes, distDir);
|
|
138
|
+
const staticPathRegExp = getStaticReg(
|
|
139
|
+
this.conf.output || {},
|
|
140
|
+
this.conf.html
|
|
141
|
+
);
|
|
142
|
+
this.staticFileHandler = createStaticFileHandler(
|
|
143
|
+
[
|
|
144
|
+
{
|
|
145
|
+
path: staticPathRegExp,
|
|
146
|
+
target: distDir
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
this.conf.output
|
|
150
|
+
);
|
|
151
|
+
this.routeRenderHandler = createRenderHandler({
|
|
152
|
+
distDir,
|
|
153
|
+
staticGenerate
|
|
122
154
|
});
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
this.
|
|
129
|
-
}); // use preset routes priority
|
|
130
|
-
|
|
131
|
-
const usageRoutes = this.filterRoutes(this.getRoutes());
|
|
132
|
-
this.router.reset(usageRoutes); // warmup ssr bundle in production env
|
|
133
|
-
|
|
134
|
-
this.warmupSSRBundle();
|
|
135
|
-
await this.prepareFrameHandler(); // Only work when without setting `assetPrefix`.
|
|
136
|
-
// Setting `assetPrefix` means these resources should be uploaded to CDN.
|
|
137
|
-
|
|
138
|
-
const staticPathRegExp = getStaticReg(this.conf.output || {});
|
|
139
|
-
this.staticFileHandler = createStaticFileHandler([{
|
|
140
|
-
path: staticPathRegExp,
|
|
141
|
-
target: distDir
|
|
142
|
-
}], this.conf.output);
|
|
143
|
-
this.routeRenderHandler = createRenderHandler({
|
|
144
|
-
distDir,
|
|
145
|
-
staticGenerate
|
|
155
|
+
yield this.setupBeforeProdMiddleware();
|
|
156
|
+
this.addHandler(this.staticFileHandler);
|
|
157
|
+
this.addHandler(faviconFallbackHandler);
|
|
158
|
+
this.addBeforeRouteHandler();
|
|
159
|
+
this.addHandler(this.routeHandler.bind(this));
|
|
160
|
+
this.compose();
|
|
146
161
|
});
|
|
147
|
-
await this.setupBeforeProdMiddleware();
|
|
148
|
-
this.addHandler(this.staticFileHandler);
|
|
149
|
-
this.addHandler(this.routeHandler.bind(this)); // compose middlewares to http handler
|
|
150
|
-
|
|
151
|
-
this.compose();
|
|
152
|
-
} // server ready
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
onRepack(_) {// empty
|
|
156
162
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
163
|
+
onRepack(_) {
|
|
164
|
+
}
|
|
165
|
+
addBeforeRouteHandler() {
|
|
166
|
+
this.addHandler((context, next) => __async(this, null, function* () {
|
|
167
|
+
if (this.beforeRouteHandler) {
|
|
168
|
+
yield this.beforeRouteHandler(context);
|
|
169
|
+
if (this.isSend(context.res)) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return next();
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
onServerChange({ filepath }) {
|
|
177
|
+
const { pwd } = this;
|
|
178
|
+
const { api, server } = AGGRED_DIR;
|
|
168
179
|
const apiPath = path.normalize(path.join(pwd, api));
|
|
169
180
|
const serverPath = path.normalize(path.join(pwd, server));
|
|
170
181
|
const onlyApi = filepath.startsWith(apiPath);
|
|
171
182
|
const onlyWeb = filepath.startsWith(serverPath);
|
|
172
|
-
this.prepareFrameHandler({
|
|
173
|
-
|
|
174
|
-
onlyApi
|
|
175
|
-
});
|
|
176
|
-
} // exposed requestHandler
|
|
177
|
-
|
|
178
|
-
|
|
183
|
+
this.prepareFrameHandler({ onlyWeb, onlyApi });
|
|
184
|
+
}
|
|
179
185
|
getRequestHandler() {
|
|
180
186
|
return this.requestHandler.bind(this);
|
|
181
187
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
188
|
+
render(req, res, url) {
|
|
189
|
+
return __async(this, null, function* () {
|
|
190
|
+
req.logger = this.logger;
|
|
191
|
+
req.metrics = this.metrics;
|
|
192
|
+
const context = createContext(req, res);
|
|
193
|
+
const matched = this.router.match(url || context.path);
|
|
194
|
+
if (!matched) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
const route = matched.generate(context.url);
|
|
198
|
+
const result = yield this.handleWeb(context, route);
|
|
199
|
+
if (!result) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return result.content.toString();
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
createHTTPServer(handler) {
|
|
206
|
+
return __async(this, null, function* () {
|
|
207
|
+
return createServer(handler);
|
|
208
|
+
});
|
|
185
209
|
}
|
|
186
|
-
/* —————————————————————— function will be overwrite —————————————————————— */
|
|
187
|
-
// get routes info
|
|
188
|
-
|
|
189
|
-
|
|
190
210
|
getRoutes() {
|
|
191
|
-
// Preferred to use preset routes
|
|
192
211
|
if (this.presetRoutes) {
|
|
193
212
|
return this.presetRoutes;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
|
|
213
|
+
}
|
|
197
214
|
const file = path.join(this.distDir, ROUTE_SPEC_FILE);
|
|
198
|
-
|
|
199
215
|
if (fs.existsSync(file)) {
|
|
200
216
|
const content = fs.readJSONSync(file);
|
|
201
217
|
return content.routes;
|
|
202
218
|
}
|
|
203
|
-
|
|
204
219
|
return [];
|
|
205
|
-
}
|
|
206
|
-
// handler should do not do more things after invoke next
|
|
207
|
-
|
|
208
|
-
|
|
220
|
+
}
|
|
209
221
|
addHandler(handler) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
} else {
|
|
213
|
-
this.handlers.push(util.promisify(handler));
|
|
214
|
-
}
|
|
215
|
-
} // return 404 page
|
|
216
|
-
|
|
217
|
-
|
|
222
|
+
this.handlers.push(handler);
|
|
223
|
+
}
|
|
218
224
|
render404(context) {
|
|
219
|
-
context.error(ERROR_DIGEST.ENOTF,
|
|
225
|
+
context.error(ERROR_DIGEST.ENOTF, "404 Not Found");
|
|
220
226
|
this.renderErrorPage(context, 404);
|
|
221
|
-
} // gather frame extension and get framework handler
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
async prepareFrameHandler(options) {
|
|
225
|
-
const {
|
|
226
|
-
workDir,
|
|
227
|
-
runner
|
|
228
|
-
} = this;
|
|
229
|
-
const {
|
|
230
|
-
onlyApi,
|
|
231
|
-
onlyWeb
|
|
232
|
-
} = options || {}; // server hook, gather plugin inject
|
|
233
|
-
|
|
234
|
-
const _createMiddlewareColl = createMiddlewareCollecter(),
|
|
235
|
-
{
|
|
236
|
-
getMiddlewares
|
|
237
|
-
} = _createMiddlewareColl,
|
|
238
|
-
collector = _objectWithoutProperties(_createMiddlewareColl, _excluded);
|
|
239
|
-
|
|
240
|
-
await runner.gather(collector);
|
|
241
|
-
const {
|
|
242
|
-
api: pluginAPIExt,
|
|
243
|
-
web: pluginWebExt
|
|
244
|
-
} = getMiddlewares();
|
|
245
|
-
const apiDir = path.join(workDir, API_DIR);
|
|
246
|
-
const serverDir = path.join(workDir, SERVER_DIR); // get api or web server handler from server-framework plugin
|
|
247
|
-
|
|
248
|
-
if ((await fs.pathExists(path.join(serverDir))) && !onlyApi) {
|
|
249
|
-
const webExtension = mergeExtension(pluginWebExt);
|
|
250
|
-
this.frameWebHandler = await this.prepareWebHandler(webExtension);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (fs.existsSync(apiDir) && !onlyWeb) {
|
|
254
|
-
const apiExtension = mergeExtension(pluginAPIExt);
|
|
255
|
-
this.frameAPIHandler = await this.prepareAPIHandler(apiExtension);
|
|
256
|
-
}
|
|
257
227
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
228
|
+
prepareBeforeRouteHandler(specs, distDir) {
|
|
229
|
+
return __async(this, null, function* () {
|
|
230
|
+
const { runner } = this;
|
|
231
|
+
const handler = yield runner.preparebeforeRouteHandler(
|
|
232
|
+
{
|
|
233
|
+
serverRoutes: specs,
|
|
234
|
+
distDir
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
onLast: () => null
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
this.beforeRouteHandler = handler;
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
prepareFrameHandler(options) {
|
|
244
|
+
return __async(this, null, function* () {
|
|
245
|
+
const { workDir, runner } = this;
|
|
246
|
+
const { onlyApi, onlyWeb } = options || {};
|
|
247
|
+
const _a = createMiddlewareCollecter(), { getMiddlewares } = _a, collector = __objRest(_a, ["getMiddlewares"]);
|
|
248
|
+
yield runner.gather(collector);
|
|
249
|
+
const { api: pluginAPIExt, web: pluginWebExt } = getMiddlewares();
|
|
250
|
+
const apiDir = path.join(workDir, API_DIR);
|
|
251
|
+
const serverDir = path.join(workDir, SERVER_DIR);
|
|
252
|
+
if ((yield fs.pathExists(path.join(serverDir))) && !onlyApi) {
|
|
253
|
+
const webExtension = mergeExtension(pluginWebExt);
|
|
254
|
+
this.frameWebHandler = yield this.prepareWebHandler(webExtension);
|
|
255
|
+
}
|
|
256
|
+
if (fs.existsSync(apiDir) && !onlyWeb) {
|
|
257
|
+
const apiExtension = mergeExtension(pluginAPIExt);
|
|
258
|
+
this.frameAPIHandler = yield this.prepareAPIHandler(apiExtension);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
prepareWebHandler(extension) {
|
|
263
|
+
return __async(this, null, function* () {
|
|
264
|
+
const { workDir, runner } = this;
|
|
265
|
+
const handler = yield runner.prepareWebServer(
|
|
266
|
+
{
|
|
267
|
+
pwd: workDir,
|
|
268
|
+
config: extension
|
|
269
|
+
},
|
|
270
|
+
{ onLast: () => null }
|
|
271
|
+
);
|
|
272
|
+
return handler;
|
|
269
273
|
});
|
|
270
274
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
config: extension,
|
|
285
|
-
prefix: Array.isArray(prefix) ? prefix[0] : prefix
|
|
286
|
-
}, {
|
|
287
|
-
onLast: () => null
|
|
275
|
+
prepareAPIHandler(extension) {
|
|
276
|
+
return __async(this, null, function* () {
|
|
277
|
+
const { workDir, runner, conf } = this;
|
|
278
|
+
const { bff } = conf;
|
|
279
|
+
const prefix = (bff == null ? void 0 : bff.prefix) || "/api";
|
|
280
|
+
return runner.prepareApiServer(
|
|
281
|
+
{
|
|
282
|
+
pwd: workDir,
|
|
283
|
+
config: extension,
|
|
284
|
+
prefix: Array.isArray(prefix) ? prefix[0] : prefix
|
|
285
|
+
},
|
|
286
|
+
{ onLast: () => null }
|
|
287
|
+
);
|
|
288
288
|
});
|
|
289
289
|
}
|
|
290
|
-
|
|
291
290
|
filterRoutes(routes) {
|
|
292
291
|
return routes;
|
|
293
292
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
293
|
+
setupBeforeProdMiddleware() {
|
|
294
|
+
return __async(this, null, function* () {
|
|
295
|
+
const { conf, runner } = this;
|
|
296
|
+
const preMiddleware = yield runner.beforeProdServer(conf);
|
|
297
|
+
preMiddleware.flat().forEach((mid) => {
|
|
298
|
+
this.addHandler(mid);
|
|
299
|
+
});
|
|
299
300
|
});
|
|
300
301
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
preMiddleware.flat().forEach(mid => {
|
|
309
|
-
this.addHandler(mid);
|
|
302
|
+
handleAPI(context) {
|
|
303
|
+
return __async(this, null, function* () {
|
|
304
|
+
const { req, res } = context;
|
|
305
|
+
if (!this.frameAPIHandler) {
|
|
306
|
+
throw new Error("can not found api handler");
|
|
307
|
+
}
|
|
308
|
+
yield this.frameAPIHandler(req, res);
|
|
310
309
|
});
|
|
311
310
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
throw new Error('can not found api handler');
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
await this.frameAPIHandler(req, res);
|
|
311
|
+
handleWeb(context, route) {
|
|
312
|
+
return __async(this, null, function* () {
|
|
313
|
+
return this.routeRenderHandler({
|
|
314
|
+
ctx: context,
|
|
315
|
+
route,
|
|
316
|
+
runner: this.runner
|
|
317
|
+
});
|
|
318
|
+
});
|
|
324
319
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
ctx: context,
|
|
329
|
-
route,
|
|
330
|
-
runner: this.runner
|
|
320
|
+
proxy() {
|
|
321
|
+
return __async(this, null, function* () {
|
|
322
|
+
return null;
|
|
331
323
|
});
|
|
332
324
|
}
|
|
333
|
-
|
|
334
|
-
async proxy() {
|
|
335
|
-
return null;
|
|
336
|
-
} // warmup ssr function
|
|
337
|
-
|
|
338
|
-
|
|
339
325
|
warmupSSRBundle() {
|
|
340
|
-
const {
|
|
341
|
-
distDir
|
|
342
|
-
} = this;
|
|
326
|
+
const { distDir } = this;
|
|
343
327
|
const bundles = this.router.getBundles();
|
|
344
|
-
bundles.forEach(bundle => {
|
|
345
|
-
const filepath = path.join(distDir, bundle);
|
|
346
|
-
|
|
328
|
+
bundles.forEach((bundle) => {
|
|
329
|
+
const filepath = path.join(distDir, bundle);
|
|
347
330
|
require(filepath);
|
|
348
331
|
});
|
|
349
332
|
}
|
|
350
|
-
|
|
351
333
|
createContext(req, res, options = {}) {
|
|
352
334
|
return createContext(req, res, options);
|
|
353
335
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
if (this.isSend(res)) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
const {
|
|
389
|
-
current
|
|
390
|
-
} = routeAPI;
|
|
391
|
-
const route = current.generate(context.url);
|
|
392
|
-
context.setParams(route.params);
|
|
393
|
-
context.setServerData('router', {
|
|
394
|
-
baseUrl: route.urlPath,
|
|
395
|
-
params: route.params
|
|
396
|
-
}); // route is api service
|
|
397
|
-
|
|
398
|
-
if (route.isApi) {
|
|
399
|
-
await this.handleAPI(context);
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (this.frameWebHandler) {
|
|
404
|
-
await this.frameWebHandler(req, res);
|
|
405
|
-
} // frameWebHandler has process request
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if (this.isSend(res)) {
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
if (route.responseHeaders) {
|
|
413
|
-
Object.keys(route.responseHeaders).forEach(key => {
|
|
414
|
-
const value = route.responseHeaders[key];
|
|
415
|
-
|
|
416
|
-
if (value) {
|
|
417
|
-
context.res.setHeader(key, value);
|
|
336
|
+
routeHandler(context) {
|
|
337
|
+
return __async(this, null, function* () {
|
|
338
|
+
const { res } = context;
|
|
339
|
+
const matched = this.router.match(context.path);
|
|
340
|
+
if (!matched) {
|
|
341
|
+
this.render404(context);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
let route = matched.generate(context.url);
|
|
345
|
+
if (route.isApi) {
|
|
346
|
+
yield this.handleAPI(context);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const afterMatchContext = createAfterMatchContext(context, route.entryName);
|
|
350
|
+
if (this.runMode === RUN_MODE.FULL) {
|
|
351
|
+
yield this.runner.afterMatch(afterMatchContext, { onLast: noop });
|
|
352
|
+
}
|
|
353
|
+
if (this.isSend(res)) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
const { current, url, status } = afterMatchContext.router;
|
|
357
|
+
if (url) {
|
|
358
|
+
this.redirect(res, url, status);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (route.entryName !== current) {
|
|
362
|
+
const matched2 = this.router.matchEntry(current);
|
|
363
|
+
if (!matched2) {
|
|
364
|
+
this.render404(context);
|
|
365
|
+
return;
|
|
418
366
|
}
|
|
367
|
+
route = matched2.generate(context.url);
|
|
368
|
+
}
|
|
369
|
+
context.setParams(route.params);
|
|
370
|
+
context.setServerData("router", {
|
|
371
|
+
baseUrl: route.urlPath,
|
|
372
|
+
params: route.params
|
|
419
373
|
});
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const file = await this.handleWeb(context, route);
|
|
429
|
-
|
|
430
|
-
if (!file) {
|
|
431
|
-
this.render404(context);
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
if (file.redirect) {
|
|
436
|
-
res.statusCode = file.statusCode;
|
|
437
|
-
res.setHeader('Location', file.content);
|
|
438
|
-
res.end();
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
if (this.isSend(res)) {
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
let response = file.content;
|
|
447
|
-
|
|
448
|
-
if (route.entryName) {
|
|
449
|
-
const templateAPI = createTemplateAPI(file.content.toString());
|
|
450
|
-
await this.emitRouteHook('afterRender', {
|
|
451
|
-
context,
|
|
452
|
-
templateAPI
|
|
453
|
-
});
|
|
454
|
-
|
|
374
|
+
if (this.frameWebHandler) {
|
|
375
|
+
res.locals = res.locals || {};
|
|
376
|
+
const middlewareContext = createMiddlewareContext(context);
|
|
377
|
+
yield this.frameWebHandler(middlewareContext);
|
|
378
|
+
res.locals = __spreadValues(__spreadValues({}, res.locals), middlewareContext.response.locals);
|
|
379
|
+
}
|
|
455
380
|
if (this.isSend(res)) {
|
|
456
381
|
return;
|
|
457
382
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
383
|
+
if (route.responseHeaders) {
|
|
384
|
+
Object.keys(route.responseHeaders).forEach((key) => {
|
|
385
|
+
const value = route.responseHeaders[key];
|
|
386
|
+
if (value) {
|
|
387
|
+
context.res.setHeader(key, value);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
const renderResult = yield this.handleWeb(context, route);
|
|
392
|
+
if (!renderResult) {
|
|
393
|
+
this.render404(context);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (renderResult.redirect) {
|
|
397
|
+
this.redirect(
|
|
398
|
+
res,
|
|
399
|
+
renderResult.content,
|
|
400
|
+
renderResult.statusCode
|
|
401
|
+
);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (this.isSend(res)) {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
res.setHeader("content-type", renderResult.contentType);
|
|
408
|
+
const { contentStream } = renderResult;
|
|
409
|
+
if (contentStream) {
|
|
410
|
+
contentStream.pipe(
|
|
411
|
+
templateInjectableStream({
|
|
412
|
+
prependHead: route.entryName ? `<script>window._SERVER_DATA=${JSON.stringify(
|
|
413
|
+
context.serverData
|
|
414
|
+
)}<\/script>` : void 0
|
|
415
|
+
})
|
|
416
|
+
).pipe(res);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
let response = renderResult.content;
|
|
420
|
+
if (route.entryName) {
|
|
421
|
+
const afterRenderContext = createAfterRenderContext(
|
|
422
|
+
context,
|
|
423
|
+
response.toString()
|
|
424
|
+
);
|
|
425
|
+
if (this.runMode === RUN_MODE.FULL) {
|
|
426
|
+
yield this.runner.afterRender(afterRenderContext, { onLast: noop });
|
|
427
|
+
}
|
|
428
|
+
if (this.isSend(res)) {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
afterRenderContext.template.prependHead(
|
|
432
|
+
`<script>window._SERVER_DATA=${JSON.stringify(
|
|
433
|
+
context.serverData
|
|
434
|
+
)}<\/script>`
|
|
435
|
+
);
|
|
436
|
+
response = afterRenderContext.template.get();
|
|
437
|
+
}
|
|
438
|
+
res.end(response);
|
|
439
|
+
});
|
|
470
440
|
}
|
|
471
|
-
|
|
472
441
|
isSend(res) {
|
|
473
442
|
if (res.headersSent) {
|
|
474
443
|
return true;
|
|
475
444
|
}
|
|
476
|
-
|
|
477
|
-
if (res.getHeader('Location') && isRedirect(res.statusCode)) {
|
|
445
|
+
if (res.getHeader("Location") && isRedirect(res.statusCode)) {
|
|
478
446
|
res.end();
|
|
479
447
|
return true;
|
|
480
448
|
}
|
|
481
|
-
|
|
482
449
|
return false;
|
|
483
450
|
}
|
|
484
|
-
|
|
485
|
-
async injectMicroFE(context, templateAPI) {
|
|
486
|
-
var _conf$runtime, _conf$server;
|
|
487
|
-
|
|
488
|
-
const {
|
|
489
|
-
conf
|
|
490
|
-
} = this;
|
|
491
|
-
const masterApp = (_conf$runtime = conf.runtime) === null || _conf$runtime === void 0 ? void 0 : _conf$runtime.masterApp; // no inject if not master App
|
|
492
|
-
|
|
493
|
-
if (!masterApp) {
|
|
494
|
-
return;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
const manifest = masterApp.manifest || {};
|
|
498
|
-
let modules = [];
|
|
499
|
-
const {
|
|
500
|
-
modules: configModules = []
|
|
501
|
-
} = manifest; // while config modules is an string, fetch data from remote
|
|
502
|
-
|
|
503
|
-
if (typeof configModules === 'string') {
|
|
504
|
-
const moduleRequestUrl = configModules;
|
|
505
|
-
|
|
506
|
-
try {
|
|
507
|
-
const {
|
|
508
|
-
data: remoteModules
|
|
509
|
-
} = await axios.get(moduleRequestUrl);
|
|
510
|
-
|
|
511
|
-
if (Array.isArray(remoteModules)) {
|
|
512
|
-
modules.push(...remoteModules);
|
|
513
|
-
}
|
|
514
|
-
} catch (e) {
|
|
515
|
-
context.error(ERROR_DIGEST.EMICROINJ, e);
|
|
516
|
-
}
|
|
517
|
-
} else if (Array.isArray(configModules)) {
|
|
518
|
-
modules.push(...configModules);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
const {
|
|
522
|
-
headers
|
|
523
|
-
} = context.req;
|
|
524
|
-
const debugName = headers['x-micro-frontend-module-name'] || context.query['__debug__micro-frontend-module-name'];
|
|
525
|
-
const debugEntry = headers['x-micro-frontend-module-entry'] || context.query['__debug__micro-frontend-module-entry']; // add debug micro App to first
|
|
526
|
-
|
|
527
|
-
if (debugName && debugEntry && (_conf$server = conf.server) !== null && _conf$server !== void 0 && _conf$server.enableMicroFrontendDebug) {
|
|
528
|
-
modules = modules.map(m => {
|
|
529
|
-
if (m.name === debugName) {
|
|
530
|
-
return {
|
|
531
|
-
name: debugName,
|
|
532
|
-
entry: debugEntry
|
|
533
|
-
};
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
return m;
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
try {
|
|
541
|
-
// Todo Safety xss
|
|
542
|
-
const injection = JSON.stringify(_objectSpread(_objectSpread({}, manifest), {}, {
|
|
543
|
-
modules
|
|
544
|
-
}));
|
|
545
|
-
templateAPI.appendHead(`<script>window.modern_manifest=${injection}</script>`);
|
|
546
|
-
} catch (e) {
|
|
547
|
-
context.error(ERROR_DIGEST.EMICROINJ, e);
|
|
548
|
-
}
|
|
549
|
-
} // compose handlers and create the final handler
|
|
550
|
-
|
|
551
|
-
|
|
552
451
|
compose() {
|
|
553
|
-
const {
|
|
554
|
-
handlers
|
|
555
|
-
} = this;
|
|
556
|
-
|
|
452
|
+
const { handlers } = this;
|
|
557
453
|
if (!Array.isArray(handlers)) {
|
|
558
|
-
throw new TypeError(
|
|
454
|
+
throw new TypeError("Middleware stack must be an array!");
|
|
559
455
|
}
|
|
560
|
-
|
|
561
456
|
for (const fn of handlers) {
|
|
562
|
-
if (typeof fn !==
|
|
563
|
-
throw new TypeError(
|
|
457
|
+
if (typeof fn !== "function") {
|
|
458
|
+
throw new TypeError("Middleware must be composed of functions!");
|
|
564
459
|
}
|
|
565
460
|
}
|
|
566
|
-
|
|
567
461
|
this._handler = (context, next) => {
|
|
568
462
|
let i = 0;
|
|
569
|
-
|
|
570
|
-
const dispatch = error => {
|
|
463
|
+
const dispatch = (error) => {
|
|
571
464
|
if (error) {
|
|
572
465
|
return this.onError(context, error);
|
|
573
466
|
}
|
|
574
|
-
|
|
575
467
|
const handler = handlers[i++];
|
|
576
|
-
|
|
577
468
|
if (!handler) {
|
|
578
469
|
return next();
|
|
579
470
|
}
|
|
580
|
-
|
|
581
|
-
|
|
471
|
+
try {
|
|
472
|
+
const result = handler(context, dispatch);
|
|
473
|
+
if (isPromise(result)) {
|
|
474
|
+
return result.catch(onError);
|
|
475
|
+
}
|
|
476
|
+
} catch (e) {
|
|
477
|
+
return onError(e);
|
|
478
|
+
}
|
|
582
479
|
};
|
|
583
|
-
|
|
584
|
-
const onError = err => {
|
|
480
|
+
const onError = (err) => {
|
|
585
481
|
this.onError(context, err);
|
|
586
482
|
};
|
|
587
|
-
|
|
588
483
|
return dispatch();
|
|
589
484
|
};
|
|
590
485
|
}
|
|
591
|
-
|
|
592
|
-
requestHandler(req, res, next = () => {// empty
|
|
486
|
+
requestHandler(req, res, next = () => {
|
|
593
487
|
}) {
|
|
594
488
|
res.statusCode = 200;
|
|
595
489
|
req.logger = this.logger;
|
|
596
490
|
req.metrics = this.metrics;
|
|
597
491
|
let context;
|
|
598
|
-
|
|
599
492
|
try {
|
|
600
493
|
context = this.createContext(req, res);
|
|
601
494
|
} catch (e) {
|
|
602
495
|
this.logger.error(e);
|
|
603
496
|
res.statusCode = 500;
|
|
604
|
-
res.setHeader(
|
|
497
|
+
res.setHeader("content-type", mime.contentType("html"));
|
|
605
498
|
return res.end(createErrorDocument(500, ERROR_PAGE_TEXT[500]));
|
|
606
499
|
}
|
|
607
|
-
|
|
608
500
|
try {
|
|
609
501
|
return this._handler(context, next);
|
|
610
502
|
} catch (err) {
|
|
611
503
|
return this.onError(context, err);
|
|
612
504
|
}
|
|
613
505
|
}
|
|
614
|
-
|
|
506
|
+
redirect(res, url, status = 302) {
|
|
507
|
+
res.setHeader("Location", url);
|
|
508
|
+
res.statusCode = status;
|
|
509
|
+
res.end();
|
|
510
|
+
}
|
|
615
511
|
onError(context, err) {
|
|
616
512
|
context.error(ERROR_DIGEST.EINTER, err);
|
|
617
513
|
this.renderErrorPage(context, 500);
|
|
618
514
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
if (file) {
|
|
645
|
-
context.res.end(file.content);
|
|
646
|
-
return;
|
|
515
|
+
renderErrorPage(context, status) {
|
|
516
|
+
return __async(this, null, function* () {
|
|
517
|
+
const { res } = context;
|
|
518
|
+
context.status = status;
|
|
519
|
+
res.setHeader("content-type", mime.contentType("html"));
|
|
520
|
+
const statusPage = `/${status}`;
|
|
521
|
+
const customErrorPage = `/_error`;
|
|
522
|
+
const matched = this.router.match(statusPage) || this.router.match(customErrorPage);
|
|
523
|
+
if (matched) {
|
|
524
|
+
const route = matched.generate(context.url);
|
|
525
|
+
const { entryName } = route;
|
|
526
|
+
if (entryName === status.toString() || entryName === "_error") {
|
|
527
|
+
try {
|
|
528
|
+
const file = yield this.routeRenderHandler({
|
|
529
|
+
route,
|
|
530
|
+
ctx: context,
|
|
531
|
+
runner: this.runner
|
|
532
|
+
});
|
|
533
|
+
if (file) {
|
|
534
|
+
context.res.end(file.content);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
} catch (e) {
|
|
647
538
|
}
|
|
648
|
-
} catch (e) {// just catch error when the rendering error occurred in the custom error page.
|
|
649
539
|
}
|
|
650
540
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
context.res.end(createErrorDocument(status, text));
|
|
541
|
+
const text = ERROR_PAGE_TEXT[status] || ERROR_PAGE_TEXT[500];
|
|
542
|
+
context.res.end(createErrorDocument(status, text));
|
|
543
|
+
});
|
|
655
544
|
}
|
|
656
|
-
|
|
657
545
|
}
|
|
658
|
-
|
|
546
|
+
export {
|
|
547
|
+
ModernServer
|
|
548
|
+
};
|