@modern-js/prod-server 2.28.0 → 2.29.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 +22 -0
- package/dist/cjs/libs/context/context.js +10 -4
- package/dist/cjs/libs/hook-api/index.js +2 -1
- package/dist/cjs/libs/hook-api/index.worker.js +2 -1
- package/dist/cjs/libs/render/ssr.js +3 -19
- package/dist/cjs/libs/reporter.js +22 -0
- package/dist/cjs/libs/serverTiming.js +27 -0
- package/dist/cjs/server/modernServer.js +23 -2
- package/dist/cjs/utils.js +33 -0
- package/dist/cjs/workerServer.js +12 -3
- package/dist/esm/libs/context/context.js +8 -2
- package/dist/esm/libs/hook-api/index.js +2 -1
- package/dist/esm/libs/hook-api/index.worker.js +2 -1
- package/dist/esm/libs/render/ssr.js +6 -29
- package/dist/esm/libs/reporter.js +12 -0
- package/dist/esm/libs/serverTiming.js +27 -0
- package/dist/esm/server/modernServer.js +57 -26
- package/dist/esm/utils.js +57 -0
- package/dist/esm/workerServer.js +13 -4
- package/dist/esm-node/libs/context/context.js +8 -2
- package/dist/esm-node/libs/hook-api/index.js +2 -1
- package/dist/esm-node/libs/hook-api/index.worker.js +2 -1
- package/dist/esm-node/libs/render/ssr.js +3 -19
- package/dist/esm-node/libs/reporter.js +12 -0
- package/dist/esm-node/libs/serverTiming.js +17 -0
- package/dist/esm-node/server/modernServer.js +24 -3
- package/dist/esm-node/utils.js +30 -0
- package/dist/esm-node/workerServer.js +12 -3
- package/dist/types/libs/context/context.d.ts +5 -2
- package/dist/types/libs/hook-api/index.worker.d.ts +2 -1
- package/dist/types/libs/reporter.d.ts +2 -0
- package/dist/types/libs/serverTiming.d.ts +12 -0
- package/dist/types/server/modernServer.d.ts +1 -1
- package/dist/types/type.d.ts +1 -0
- package/dist/types/utils.d.ts +3 -2
- package/package.json +8 -8
|
@@ -8,10 +8,11 @@ import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
|
8
8
|
import { createServer } from "http";
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { fs, isPromise, isWebOnly, mime, ROUTE_SPEC_FILE } from "@modern-js/utils";
|
|
11
|
+
import { time } from "@modern-js/utils/universal/time";
|
|
11
12
|
import { RouteMatchManager } from "../libs/route";
|
|
12
13
|
import { createRenderHandler } from "../libs/render";
|
|
13
14
|
import { createStaticFileHandler, faviconFallbackHandler } from "../libs/serveFile";
|
|
14
|
-
import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop, debug, isRedirect } from "../utils";
|
|
15
|
+
import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop, debug, isRedirect, bodyParser } from "../utils";
|
|
15
16
|
import * as reader from "../libs/render/reader";
|
|
16
17
|
import { createProxyHandler } from "../libs/proxy";
|
|
17
18
|
import { createContext } from "../libs/context";
|
|
@@ -164,7 +165,9 @@ export var ModernServer = /* @__PURE__ */ function() {
|
|
|
164
165
|
case 0:
|
|
165
166
|
req.logger = req.logger || _this.logger;
|
|
166
167
|
req.metrics = req.metrics || _this.metrics;
|
|
167
|
-
context = createContext(req, res
|
|
168
|
+
context = createContext(req, res, {
|
|
169
|
+
metaName: _this.metaName
|
|
170
|
+
});
|
|
168
171
|
matched = _this.router.match(url || context.path);
|
|
169
172
|
if (!matched) {
|
|
170
173
|
return [
|
|
@@ -666,11 +669,11 @@ export var ModernServer = /* @__PURE__ */ function() {
|
|
|
666
669
|
function routeHandler(context) {
|
|
667
670
|
var _this = this;
|
|
668
671
|
return _async_to_generator(function() {
|
|
669
|
-
var res, matched, route, afterMatchContext, _afterMatchContext_router, current, url, status, matched1, middlewareContext, renderResult, responseStream, response, afterRenderContext;
|
|
672
|
+
var res, req, reporter, matched, end, route, afterMatchContext, end1, cost, _afterMatchContext_router, current, url, status, matched1, middlewareContext, end2, cost1, renderResult, responseStream, response, afterRenderContext, end3, cost2;
|
|
670
673
|
return _ts_generator(this, function(_state) {
|
|
671
674
|
switch (_state.label) {
|
|
672
675
|
case 0:
|
|
673
|
-
res = context.res;
|
|
676
|
+
res = context.res, req = context.req, reporter = context.reporter;
|
|
674
677
|
matched = _this.router.match(context.path);
|
|
675
678
|
if (!matched) {
|
|
676
679
|
_this.render404(context);
|
|
@@ -678,43 +681,65 @@ export var ModernServer = /* @__PURE__ */ function() {
|
|
|
678
681
|
2
|
|
679
682
|
];
|
|
680
683
|
}
|
|
684
|
+
return [
|
|
685
|
+
4,
|
|
686
|
+
reporter.init({
|
|
687
|
+
match: matched
|
|
688
|
+
})
|
|
689
|
+
];
|
|
690
|
+
case 1:
|
|
691
|
+
_state.sent();
|
|
692
|
+
end = time();
|
|
693
|
+
res.on("finish", function() {
|
|
694
|
+
var cost3 = end();
|
|
695
|
+
reporter.reportTiming("server_handle_request", cost3);
|
|
696
|
+
});
|
|
681
697
|
route = matched.generate(context.url);
|
|
682
698
|
if (!route.isApi)
|
|
683
699
|
return [
|
|
684
700
|
3,
|
|
685
|
-
|
|
701
|
+
3
|
|
686
702
|
];
|
|
687
703
|
return [
|
|
688
704
|
4,
|
|
689
705
|
_this.handleAPI(context)
|
|
690
706
|
];
|
|
691
|
-
case
|
|
707
|
+
case 2:
|
|
692
708
|
_state.sent();
|
|
693
709
|
return [
|
|
694
710
|
2
|
|
695
711
|
];
|
|
696
|
-
case
|
|
712
|
+
case 3:
|
|
713
|
+
return [
|
|
714
|
+
4,
|
|
715
|
+
bodyParser(req)
|
|
716
|
+
];
|
|
717
|
+
case 4:
|
|
718
|
+
_state.sent();
|
|
697
719
|
if (!route.entryName)
|
|
698
720
|
return [
|
|
699
721
|
3,
|
|
700
|
-
|
|
722
|
+
7
|
|
701
723
|
];
|
|
702
724
|
afterMatchContext = createAfterMatchContext(context, route.entryName);
|
|
703
725
|
if (!(_this.runMode === RUN_MODE.FULL))
|
|
704
726
|
return [
|
|
705
727
|
3,
|
|
706
|
-
|
|
728
|
+
6
|
|
707
729
|
];
|
|
730
|
+
end1 = time();
|
|
708
731
|
return [
|
|
709
732
|
4,
|
|
710
733
|
_this.runner.afterMatch(afterMatchContext, {
|
|
711
734
|
onLast: noop
|
|
712
735
|
})
|
|
713
736
|
];
|
|
714
|
-
case
|
|
737
|
+
case 5:
|
|
715
738
|
_state.sent();
|
|
716
|
-
|
|
717
|
-
|
|
739
|
+
cost = end1();
|
|
740
|
+
reporter.reportTiming("server_hook_after_render", cost);
|
|
741
|
+
_state.label = 6;
|
|
742
|
+
case 6:
|
|
718
743
|
if (_this.isSend(res)) {
|
|
719
744
|
return [
|
|
720
745
|
2
|
|
@@ -737,34 +762,37 @@ export var ModernServer = /* @__PURE__ */ function() {
|
|
|
737
762
|
}
|
|
738
763
|
route = matched1.generate(context.url);
|
|
739
764
|
}
|
|
740
|
-
_state.label =
|
|
741
|
-
case
|
|
765
|
+
_state.label = 7;
|
|
766
|
+
case 7:
|
|
742
767
|
if (!_this.frameWebHandler)
|
|
743
768
|
return [
|
|
744
769
|
3,
|
|
745
|
-
|
|
770
|
+
9
|
|
746
771
|
];
|
|
747
772
|
res.locals = res.locals || {};
|
|
748
773
|
middlewareContext = createMiddlewareContext(context);
|
|
774
|
+
end2 = time();
|
|
749
775
|
return [
|
|
750
776
|
4,
|
|
751
777
|
_this.frameWebHandler(middlewareContext)
|
|
752
778
|
];
|
|
753
|
-
case
|
|
779
|
+
case 8:
|
|
754
780
|
_state.sent();
|
|
781
|
+
cost1 = end2();
|
|
782
|
+
reporter.reportTiming("server_middleware", cost1);
|
|
755
783
|
res.locals = _object_spread({}, res.locals, middlewareContext.response.locals);
|
|
756
784
|
if (_this.isSend(res)) {
|
|
757
785
|
return [
|
|
758
786
|
2
|
|
759
787
|
];
|
|
760
788
|
}
|
|
761
|
-
_state.label =
|
|
762
|
-
case
|
|
789
|
+
_state.label = 9;
|
|
790
|
+
case 9:
|
|
763
791
|
return [
|
|
764
792
|
4,
|
|
765
793
|
_this.handleWeb(context, route)
|
|
766
794
|
];
|
|
767
|
-
case
|
|
795
|
+
case 10:
|
|
768
796
|
renderResult = _state.sent();
|
|
769
797
|
if (!renderResult) {
|
|
770
798
|
return [
|
|
@@ -782,32 +810,35 @@ export var ModernServer = /* @__PURE__ */ function() {
|
|
|
782
810
|
if (!route.entryName)
|
|
783
811
|
return [
|
|
784
812
|
3,
|
|
785
|
-
|
|
813
|
+
13
|
|
786
814
|
];
|
|
787
815
|
afterRenderContext = createAfterRenderContext(context, response.toString());
|
|
788
816
|
if (!(_this.runMode === RUN_MODE.FULL))
|
|
789
817
|
return [
|
|
790
818
|
3,
|
|
791
|
-
|
|
819
|
+
12
|
|
792
820
|
];
|
|
821
|
+
end3 = time();
|
|
793
822
|
return [
|
|
794
823
|
4,
|
|
795
824
|
_this.runner.afterRender(afterRenderContext, {
|
|
796
825
|
onLast: noop
|
|
797
826
|
})
|
|
798
827
|
];
|
|
799
|
-
case
|
|
828
|
+
case 11:
|
|
800
829
|
_state.sent();
|
|
801
|
-
|
|
802
|
-
|
|
830
|
+
cost2 = end3();
|
|
831
|
+
reporter.reportTiming("server_hook_after_render", cost2);
|
|
832
|
+
_state.label = 12;
|
|
833
|
+
case 12:
|
|
803
834
|
if (_this.isSend(res)) {
|
|
804
835
|
return [
|
|
805
836
|
2
|
|
806
837
|
];
|
|
807
838
|
}
|
|
808
839
|
response = afterRenderContext.template.get();
|
|
809
|
-
_state.label =
|
|
810
|
-
case
|
|
840
|
+
_state.label = 13;
|
|
841
|
+
case 13:
|
|
811
842
|
res.end(response);
|
|
812
843
|
return [
|
|
813
844
|
2
|
package/dist/esm/utils.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
|
|
1
2
|
import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
|
|
2
3
|
import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array";
|
|
4
|
+
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
3
5
|
import { createDebugger } from "@modern-js/utils";
|
|
4
6
|
export var debug = createDebugger("prod-server");
|
|
5
7
|
export var mergeExtension = function(users) {
|
|
@@ -90,3 +92,58 @@ export var isRedirect = function(code) {
|
|
|
90
92
|
308
|
|
91
93
|
].includes(code);
|
|
92
94
|
};
|
|
95
|
+
function parseBodyTypes(headers, body) {
|
|
96
|
+
switch (headers["content-type"]) {
|
|
97
|
+
case "application/json":
|
|
98
|
+
return JSON.parse(body);
|
|
99
|
+
default:
|
|
100
|
+
return body;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
var getRequestBody = function(req) {
|
|
104
|
+
return new Promise(function(resolve, reject) {
|
|
105
|
+
var _req;
|
|
106
|
+
if (((_req = req) === null || _req === void 0 ? void 0 : _req.method) && req.method.toLowerCase() !== "get") {
|
|
107
|
+
var body = "";
|
|
108
|
+
req.on("data", function(chunk) {
|
|
109
|
+
body += chunk.toString();
|
|
110
|
+
});
|
|
111
|
+
req.on("end", function() {
|
|
112
|
+
resolve(parseBodyTypes(req.headers, body));
|
|
113
|
+
});
|
|
114
|
+
req.on("error", function(err) {
|
|
115
|
+
reject(err);
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
resolve(void 0);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
export var bodyParser = function() {
|
|
123
|
+
var _ref = _async_to_generator(function(req) {
|
|
124
|
+
return _ts_generator(this, function(_state) {
|
|
125
|
+
switch (_state.label) {
|
|
126
|
+
case 0:
|
|
127
|
+
if (!!req.body)
|
|
128
|
+
return [
|
|
129
|
+
3,
|
|
130
|
+
2
|
|
131
|
+
];
|
|
132
|
+
return [
|
|
133
|
+
4,
|
|
134
|
+
getRequestBody(req)
|
|
135
|
+
];
|
|
136
|
+
case 1:
|
|
137
|
+
req.body = _state.sent();
|
|
138
|
+
_state.label = 2;
|
|
139
|
+
case 2:
|
|
140
|
+
return [
|
|
141
|
+
2
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
return function bodyParser2(req) {
|
|
147
|
+
return _ref.apply(this, arguments);
|
|
148
|
+
};
|
|
149
|
+
}();
|
package/dist/esm/workerServer.js
CHANGED
|
@@ -9,6 +9,7 @@ import { createAfterMatchContext, createAfterRenderContext, createMiddlewareCont
|
|
|
9
9
|
import { Logger } from "./libs/logger";
|
|
10
10
|
import { RouteMatchManager } from "./libs/route";
|
|
11
11
|
import { metrics as defaultMetrics } from "./libs/metrics";
|
|
12
|
+
import { defaultReporter } from "./libs/reporter";
|
|
12
13
|
export var ReturnResponse = /* @__PURE__ */ function() {
|
|
13
14
|
"use strict";
|
|
14
15
|
function ReturnResponse2(body, status) {
|
|
@@ -91,7 +92,7 @@ export var createHandler = function(manifest) {
|
|
|
91
92
|
routeMgr.reset(routes);
|
|
92
93
|
return function() {
|
|
93
94
|
var _ref = _async_to_generator(function(options) {
|
|
94
|
-
var _page_serverHooks_afterMatch, _page_serverHooks, _page, request, loadableStats, routeManifest, url, pageMatch, entryName, page, logger, metrics, hookContext, afterMatchHookContext, _page_serverHooks1, _page_serverHooks_afterRender, _page_serverHooks2, middlewarsHookContext, responseLike, params, baseUrl, serverRenderContext, body, afterRenderHookContext, e;
|
|
95
|
+
var _page_serverHooks_afterMatch, _page_serverHooks, _page, request, loadableStats, routeManifest, url, pageMatch, entryName, page, logger, metrics, reporter, hookContext, afterMatchHookContext, _page_serverHooks1, _page_serverHooks_afterRender, _page_serverHooks2, middlewarsHookContext, responseLike, params, baseUrl, serverRenderContext, body, afterRenderHookContext, e;
|
|
95
96
|
function createServerRequest(url2, baseUrl2, request2, params2) {
|
|
96
97
|
var pathname = url2.pathname, host = url2.host, searchParams = url2.searchParams;
|
|
97
98
|
var rawHeaders = request2.headers;
|
|
@@ -128,7 +129,8 @@ export var createHandler = function(manifest) {
|
|
|
128
129
|
level: "warn"
|
|
129
130
|
});
|
|
130
131
|
metrics = defaultMetrics;
|
|
131
|
-
|
|
132
|
+
reporter = defaultReporter;
|
|
133
|
+
hookContext = createWorkerHookContext(request.url, logger, metrics, reporter);
|
|
132
134
|
afterMatchHookContext = createAfterMatchContext(hookContext, entryName);
|
|
133
135
|
(_page = page) === null || _page === void 0 ? void 0 : (_page_serverHooks = _page.serverHooks) === null || _page_serverHooks === void 0 ? void 0 : (_page_serverHooks_afterMatch = _page_serverHooks.afterMatch) === null || _page_serverHooks_afterMatch === void 0 ? void 0 : _page_serverHooks_afterMatch.call(_page_serverHooks, afterMatchHookContext, function() {
|
|
134
136
|
return void 0;
|
|
@@ -182,9 +184,15 @@ export var createHandler = function(manifest) {
|
|
|
182
184
|
template: page.template,
|
|
183
185
|
entryName: page.entryName,
|
|
184
186
|
logger: logger,
|
|
187
|
+
reporter: defaultReporter,
|
|
185
188
|
metrics: metrics,
|
|
186
189
|
// FIXME: pass correctly req & res
|
|
187
190
|
req: request,
|
|
191
|
+
serverTiming: {
|
|
192
|
+
addServeTiming: function addServeTiming() {
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
},
|
|
188
196
|
res: responseLike
|
|
189
197
|
};
|
|
190
198
|
return [
|
|
@@ -236,7 +244,7 @@ function createResponse(template) {
|
|
|
236
244
|
return RESPONSE_NOTFOUND;
|
|
237
245
|
}
|
|
238
246
|
}
|
|
239
|
-
function createWorkerHookContext(url, logger, metrics) {
|
|
247
|
+
function createWorkerHookContext(url, logger, metrics, reporter) {
|
|
240
248
|
var _ref = [
|
|
241
249
|
{
|
|
242
250
|
headers: new Headers(),
|
|
@@ -250,7 +258,8 @@ function createWorkerHookContext(url, logger, metrics) {
|
|
|
250
258
|
res: res,
|
|
251
259
|
req: req,
|
|
252
260
|
logger: logger,
|
|
253
|
-
metrics: metrics
|
|
261
|
+
metrics: metrics,
|
|
262
|
+
reporter: reporter
|
|
254
263
|
};
|
|
255
264
|
}
|
|
256
265
|
function applyMiddlewares(ctx, middleware) {
|
|
@@ -4,6 +4,9 @@ import qs from "querystring";
|
|
|
4
4
|
import { Buffer } from "buffer";
|
|
5
5
|
import createEtag from "etag";
|
|
6
6
|
import fresh from "fresh";
|
|
7
|
+
import { cutNameByHyphen } from "@modern-js/utils";
|
|
8
|
+
import { ServerTiming } from "../serverTiming";
|
|
9
|
+
import { defaultReporter } from "../reporter";
|
|
7
10
|
import { headersWithoutCookie } from "../../utils";
|
|
8
11
|
const MOCK_URL_BASE = "https://modernjs.dev/";
|
|
9
12
|
export class ModernServerContext {
|
|
@@ -149,15 +152,18 @@ export class ModernServerContext {
|
|
|
149
152
|
this.logger.error(`Web Server Error - ${dig}, error = %s, req.url = %s, req.headers = %o`, e instanceof Error ? e.stack || e.message : e, this.path, headersWithoutCookie(this.headers));
|
|
150
153
|
}
|
|
151
154
|
constructor(req, res, options) {
|
|
155
|
+
var _options;
|
|
152
156
|
_define_property(this, "req", void 0);
|
|
153
157
|
_define_property(this, "res", void 0);
|
|
154
158
|
_define_property(this, "params", {});
|
|
155
|
-
_define_property(this, "
|
|
159
|
+
_define_property(this, "reporter", defaultReporter);
|
|
160
|
+
_define_property(this, "serverTiming", void 0);
|
|
161
|
+
_define_property(this, "serverData", {});
|
|
156
162
|
_define_property(this, "options", {});
|
|
157
163
|
this.req = req;
|
|
158
164
|
this.res = res;
|
|
159
165
|
this.options = options || {};
|
|
160
|
-
this.
|
|
166
|
+
this.serverTiming = new ServerTiming(res, cutNameByHyphen(((_options = options) === null || _options === void 0 ? void 0 : _options.metaName) || "modern-js"));
|
|
161
167
|
this.bind();
|
|
162
168
|
}
|
|
163
169
|
}
|
|
@@ -2,10 +2,11 @@ import { RouteAPI } from "./route";
|
|
|
2
2
|
import { TemplateAPI } from "./template";
|
|
3
3
|
import { BaseRequest, BaseResponse } from "./base";
|
|
4
4
|
export const base = (context) => {
|
|
5
|
-
const { res } = context;
|
|
5
|
+
const { res, reporter } = context;
|
|
6
6
|
return {
|
|
7
7
|
response: new BaseResponse(res),
|
|
8
8
|
request: new BaseRequest(context),
|
|
9
|
+
reporter,
|
|
9
10
|
logger: context.logger,
|
|
10
11
|
metrics: context.metrics
|
|
11
12
|
};
|
|
@@ -31,7 +31,7 @@ class ServerResponse {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
export const base = (context) => {
|
|
34
|
-
const { req, res, logger, metrics } = context;
|
|
34
|
+
const { req, res, logger, metrics, reporter } = context;
|
|
35
35
|
const serverResponse = new ServerResponse(res);
|
|
36
36
|
const { host, pathname, searchParams } = new URL(req.url);
|
|
37
37
|
const headers = {};
|
|
@@ -40,6 +40,7 @@ export const base = (context) => {
|
|
|
40
40
|
});
|
|
41
41
|
return {
|
|
42
42
|
response: new BaseResponse(serverResponse),
|
|
43
|
+
reporter,
|
|
43
44
|
request: new BaseRequest({
|
|
44
45
|
url: req.url,
|
|
45
46
|
host,
|
|
@@ -11,7 +11,6 @@ export const render = async (ctx, renderOptions, runner) => {
|
|
|
11
11
|
const loadableStats = fs.existsSync(loadableUri) ? require(loadableUri) : "";
|
|
12
12
|
const routesManifestUri = path.join(distDir, ROUTE_MANIFEST_FILE);
|
|
13
13
|
const routeManifest = fs.existsSync(routesManifestUri) ? require(routesManifestUri) : void 0;
|
|
14
|
-
const body = await getRequestBody(ctx.req);
|
|
15
14
|
const context = {
|
|
16
15
|
request: {
|
|
17
16
|
baseUrl: urlPath,
|
|
@@ -21,7 +20,7 @@ export const render = async (ctx, renderOptions, runner) => {
|
|
|
21
20
|
query: ctx.query,
|
|
22
21
|
url: ctx.href,
|
|
23
22
|
headers: ctx.headers,
|
|
24
|
-
body
|
|
23
|
+
body: ctx.req.body
|
|
25
24
|
},
|
|
26
25
|
response: {
|
|
27
26
|
setHeader: (key, value) => {
|
|
@@ -40,6 +39,8 @@ export const render = async (ctx, renderOptions, runner) => {
|
|
|
40
39
|
staticGenerate,
|
|
41
40
|
logger: void 0,
|
|
42
41
|
metrics: void 0,
|
|
42
|
+
reporter: ctx.reporter,
|
|
43
|
+
serverTiming: ctx.serverTiming,
|
|
43
44
|
req: ctx.req,
|
|
44
45
|
res: ctx.res,
|
|
45
46
|
enableUnsafeCtx,
|
|
@@ -73,20 +74,3 @@ export const render = async (ctx, renderOptions, runner) => {
|
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
};
|
|
76
|
-
const getRequestBody = (req) => new Promise((resolve, reject) => {
|
|
77
|
-
var _req;
|
|
78
|
-
if (((_req = req) === null || _req === void 0 ? void 0 : _req.method) && req.method.toLowerCase() !== "get") {
|
|
79
|
-
let body = "";
|
|
80
|
-
req.on("data", (chunk) => {
|
|
81
|
-
body += chunk.toString();
|
|
82
|
-
});
|
|
83
|
-
req.on("end", () => {
|
|
84
|
-
resolve(body);
|
|
85
|
-
});
|
|
86
|
-
req.on("error", (err) => {
|
|
87
|
-
reject(err);
|
|
88
|
-
});
|
|
89
|
-
} else {
|
|
90
|
-
resolve(void 0);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
const SERVER_TIMING = "Server-Timing";
|
|
3
|
+
export class ServerTiming {
|
|
4
|
+
addServeTiming(name, dur, desc) {
|
|
5
|
+
const _name = `bd-${this.meta}-${name}`;
|
|
6
|
+
const serverTiming = this.res.getHeader(SERVER_TIMING) || this.res.getHeader(SERVER_TIMING.toLocaleLowerCase());
|
|
7
|
+
const value = `${_name};${desc ? `decs="${desc}";` : ""} dur=${dur}`;
|
|
8
|
+
this.res.setHeader(SERVER_TIMING, serverTiming ? `${serverTiming}, ${value}` : value);
|
|
9
|
+
return this;
|
|
10
|
+
}
|
|
11
|
+
constructor(res, meta) {
|
|
12
|
+
_define_property(this, "meta", void 0);
|
|
13
|
+
_define_property(this, "res", void 0);
|
|
14
|
+
this.meta = meta;
|
|
15
|
+
this.res = res;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -2,10 +2,11 @@ import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
|
2
2
|
import { createServer } from "http";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { fs, isPromise, isWebOnly, mime, ROUTE_SPEC_FILE } from "@modern-js/utils";
|
|
5
|
+
import { time } from "@modern-js/utils/universal/time";
|
|
5
6
|
import { RouteMatchManager } from "../libs/route";
|
|
6
7
|
import { createRenderHandler } from "../libs/render";
|
|
7
8
|
import { createStaticFileHandler, faviconFallbackHandler } from "../libs/serveFile";
|
|
8
|
-
import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop, debug, isRedirect } from "../utils";
|
|
9
|
+
import { createErrorDocument, createMiddlewareCollecter, getStaticReg, mergeExtension, noop, debug, isRedirect, bodyParser } from "../utils";
|
|
9
10
|
import * as reader from "../libs/render/reader";
|
|
10
11
|
import { createProxyHandler } from "../libs/proxy";
|
|
11
12
|
import { createContext } from "../libs/context";
|
|
@@ -64,7 +65,9 @@ export class ModernServer {
|
|
|
64
65
|
async render(req, res, url) {
|
|
65
66
|
req.logger = req.logger || this.logger;
|
|
66
67
|
req.metrics = req.metrics || this.metrics;
|
|
67
|
-
const context = createContext(req, res
|
|
68
|
+
const context = createContext(req, res, {
|
|
69
|
+
metaName: this.metaName
|
|
70
|
+
});
|
|
68
71
|
const matched = this.router.match(url || context.path);
|
|
69
72
|
if (!matched) {
|
|
70
73
|
return null;
|
|
@@ -265,23 +268,35 @@ export class ModernServer {
|
|
|
265
268
|
/* —————————————————————— private function —————————————————————— */
|
|
266
269
|
// handler route.json, include api / csr / ssr
|
|
267
270
|
async routeHandler(context) {
|
|
268
|
-
const { res } = context;
|
|
271
|
+
const { res, req, reporter } = context;
|
|
269
272
|
const matched = this.router.match(context.path);
|
|
270
273
|
if (!matched) {
|
|
271
274
|
this.render404(context);
|
|
272
275
|
return;
|
|
273
276
|
}
|
|
277
|
+
await reporter.init({
|
|
278
|
+
match: matched
|
|
279
|
+
});
|
|
280
|
+
const end = time();
|
|
281
|
+
res.on("finish", () => {
|
|
282
|
+
const cost = end();
|
|
283
|
+
reporter.reportTiming("server_handle_request", cost);
|
|
284
|
+
});
|
|
274
285
|
let route = matched.generate(context.url);
|
|
275
286
|
if (route.isApi) {
|
|
276
287
|
await this.handleAPI(context);
|
|
277
288
|
return;
|
|
278
289
|
}
|
|
290
|
+
await bodyParser(req);
|
|
279
291
|
if (route.entryName) {
|
|
280
292
|
const afterMatchContext = createAfterMatchContext(context, route.entryName);
|
|
281
293
|
if (this.runMode === RUN_MODE.FULL) {
|
|
294
|
+
const end2 = time();
|
|
282
295
|
await this.runner.afterMatch(afterMatchContext, {
|
|
283
296
|
onLast: noop
|
|
284
297
|
});
|
|
298
|
+
const cost = end2();
|
|
299
|
+
reporter.reportTiming("server_hook_after_render", cost);
|
|
285
300
|
}
|
|
286
301
|
if (this.isSend(res)) {
|
|
287
302
|
return;
|
|
@@ -303,7 +318,10 @@ export class ModernServer {
|
|
|
303
318
|
if (this.frameWebHandler) {
|
|
304
319
|
res.locals = res.locals || {};
|
|
305
320
|
const middlewareContext = createMiddlewareContext(context);
|
|
321
|
+
const end2 = time();
|
|
306
322
|
await this.frameWebHandler(middlewareContext);
|
|
323
|
+
const cost = end2();
|
|
324
|
+
reporter.reportTiming("server_middleware", cost);
|
|
307
325
|
res.locals = {
|
|
308
326
|
...res.locals,
|
|
309
327
|
...middlewareContext.response.locals
|
|
@@ -325,9 +343,12 @@ export class ModernServer {
|
|
|
325
343
|
if (route.entryName) {
|
|
326
344
|
const afterRenderContext = createAfterRenderContext(context, response.toString());
|
|
327
345
|
if (this.runMode === RUN_MODE.FULL) {
|
|
346
|
+
const end2 = time();
|
|
328
347
|
await this.runner.afterRender(afterRenderContext, {
|
|
329
348
|
onLast: noop
|
|
330
349
|
});
|
|
350
|
+
const cost = end2();
|
|
351
|
+
reporter.reportTiming("server_hook_after_render", cost);
|
|
331
352
|
}
|
|
332
353
|
if (this.isSend(res)) {
|
|
333
354
|
return;
|
package/dist/esm-node/utils.js
CHANGED
|
@@ -119,3 +119,33 @@ export const isRedirect = (code) => {
|
|
|
119
119
|
308
|
|
120
120
|
].includes(code);
|
|
121
121
|
};
|
|
122
|
+
function parseBodyTypes(headers, body) {
|
|
123
|
+
switch (headers["content-type"]) {
|
|
124
|
+
case "application/json":
|
|
125
|
+
return JSON.parse(body);
|
|
126
|
+
default:
|
|
127
|
+
return body;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const getRequestBody = (req) => new Promise((resolve, reject) => {
|
|
131
|
+
var _req;
|
|
132
|
+
if (((_req = req) === null || _req === void 0 ? void 0 : _req.method) && req.method.toLowerCase() !== "get") {
|
|
133
|
+
let body = "";
|
|
134
|
+
req.on("data", (chunk) => {
|
|
135
|
+
body += chunk.toString();
|
|
136
|
+
});
|
|
137
|
+
req.on("end", () => {
|
|
138
|
+
resolve(parseBodyTypes(req.headers, body));
|
|
139
|
+
});
|
|
140
|
+
req.on("error", (err) => {
|
|
141
|
+
reject(err);
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
resolve(void 0);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
export const bodyParser = async (req) => {
|
|
148
|
+
if (!req.body) {
|
|
149
|
+
req.body = await getRequestBody(req);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
@@ -4,6 +4,7 @@ import { createAfterMatchContext, createAfterRenderContext, createMiddlewareCont
|
|
|
4
4
|
import { Logger } from "./libs/logger";
|
|
5
5
|
import { RouteMatchManager } from "./libs/route";
|
|
6
6
|
import { metrics as defaultMetrics } from "./libs/metrics";
|
|
7
|
+
import { defaultReporter } from "./libs/reporter";
|
|
7
8
|
export class ReturnResponse {
|
|
8
9
|
/**
|
|
9
10
|
* Iterate a Object
|
|
@@ -82,7 +83,8 @@ export const createHandler = (manifest) => {
|
|
|
82
83
|
level: "warn"
|
|
83
84
|
});
|
|
84
85
|
const metrics = defaultMetrics;
|
|
85
|
-
const
|
|
86
|
+
const reporter = defaultReporter;
|
|
87
|
+
const hookContext = createWorkerHookContext(request.url, logger, metrics, reporter);
|
|
86
88
|
const afterMatchHookContext = createAfterMatchContext(hookContext, entryName);
|
|
87
89
|
(_page = page) === null || _page === void 0 ? void 0 : (_page_serverHooks = _page.serverHooks) === null || _page_serverHooks === void 0 ? void 0 : (_page_serverHooks_afterMatch = _page_serverHooks.afterMatch) === null || _page_serverHooks_afterMatch === void 0 ? void 0 : _page_serverHooks_afterMatch.call(_page_serverHooks, afterMatchHookContext, () => void 0);
|
|
88
90
|
if (checkIsSent(hookContext)) {
|
|
@@ -118,9 +120,15 @@ export const createHandler = (manifest) => {
|
|
|
118
120
|
template: page.template,
|
|
119
121
|
entryName: page.entryName,
|
|
120
122
|
logger,
|
|
123
|
+
reporter: defaultReporter,
|
|
121
124
|
metrics,
|
|
122
125
|
// FIXME: pass correctly req & res
|
|
123
126
|
req: request,
|
|
127
|
+
serverTiming: {
|
|
128
|
+
addServeTiming() {
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
},
|
|
124
132
|
res: responseLike
|
|
125
133
|
};
|
|
126
134
|
const body = await page.serverRender(serverRenderContext);
|
|
@@ -165,7 +173,7 @@ function createResponse(template) {
|
|
|
165
173
|
return RESPONSE_NOTFOUND;
|
|
166
174
|
}
|
|
167
175
|
}
|
|
168
|
-
function createWorkerHookContext(url, logger, metrics) {
|
|
176
|
+
function createWorkerHookContext(url, logger, metrics, reporter) {
|
|
169
177
|
const [res, req] = [
|
|
170
178
|
{
|
|
171
179
|
headers: new Headers(),
|
|
@@ -179,7 +187,8 @@ function createWorkerHookContext(url, logger, metrics) {
|
|
|
179
187
|
res,
|
|
180
188
|
req,
|
|
181
189
|
logger,
|
|
182
|
-
metrics
|
|
190
|
+
metrics,
|
|
191
|
+
reporter
|
|
183
192
|
};
|
|
184
193
|
}
|
|
185
194
|
function applyMiddlewares(ctx, middleware) {
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
/// <reference types="node" />
|
|
3
3
|
/// <reference types="node" />
|
|
4
4
|
/// <reference types="node/http" />
|
|
5
|
-
/// <reference types=".dts-temp/
|
|
5
|
+
/// <reference types=".dts-temp/rFczrZA4GO714tUiIeLuz/src/type" />
|
|
6
6
|
import { IncomingMessage, ServerResponse } from 'http';
|
|
7
7
|
import qs from 'querystring';
|
|
8
|
-
import type { ModernServerContext as ModernServerContextInterface } from '@modern-js/types';
|
|
8
|
+
import type { ModernServerContext as ModernServerContextInterface, Reporter as ModernServerReporter, ServerTiming as ModernServerTiming } from '@modern-js/types';
|
|
9
9
|
export type ContextOptions = {
|
|
10
|
+
metaName?: string;
|
|
10
11
|
etag?: boolean;
|
|
11
12
|
};
|
|
12
13
|
type ResponseBody = string | Buffer;
|
|
@@ -23,6 +24,8 @@ export declare class ModernServerContext implements ModernServerContextInterface
|
|
|
23
24
|
* url params
|
|
24
25
|
*/
|
|
25
26
|
params: Record<string, string>;
|
|
27
|
+
reporter: ModernServerReporter;
|
|
28
|
+
serverTiming: ModernServerTiming;
|
|
26
29
|
get logger(): import("@modern-js/types").Logger;
|
|
27
30
|
get metrics(): import("@modern-js/types").Metrics;
|
|
28
31
|
serverData: Record<string, any>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AfterMatchContext, AfterRenderContext, HookContext, Logger, Metrics, MiddlewareContext } from '@modern-js/types/server';
|
|
1
|
+
import { AfterMatchContext, AfterRenderContext, HookContext, Logger, Metrics, MiddlewareContext, Reporter } from '@modern-js/types/server';
|
|
2
2
|
export interface WorkerResponse {
|
|
3
3
|
headers: Headers;
|
|
4
4
|
status: number;
|
|
@@ -10,6 +10,7 @@ export interface WorkerServerContext {
|
|
|
10
10
|
res: WorkerResponse;
|
|
11
11
|
req: Request;
|
|
12
12
|
logger: Logger;
|
|
13
|
+
reporter: Reporter;
|
|
13
14
|
metrics: Metrics;
|
|
14
15
|
}
|
|
15
16
|
export declare const base: (context: WorkerServerContext) => HookContext;
|