@midwayjs/koa 3.0.0-beta.6 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/config/config.default.d.ts +51 -0
- package/dist/config/config.default.js +61 -0
- package/dist/configuration.d.ts +4 -1
- package/dist/configuration.js +23 -1
- package/dist/framework.d.ts +2 -1
- package/dist/framework.js +46 -19
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/interface.d.ts +81 -12
- package/dist/middleware/bodyparser.middleware.d.ts +6 -0
- package/dist/middleware/bodyparser.middleware.js +34 -0
- package/dist/middleware/fav.middleware.d.ts +6 -0
- package/dist/middleware/fav.middleware.js +62 -0
- package/dist/onerror.d.ts +2 -0
- package/dist/onerror.js +176 -0
- package/dist/utils.d.ts +14 -0
- package/dist/utils.js +142 -0
- package/package.json +15 -16
- package/CHANGELOG.md +0 -962
package/dist/onerror.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setupOnerror = void 0;
|
|
4
|
+
const http = require("http");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
function setupOnerror(app, config, logger) {
|
|
7
|
+
const errorOptions = Object.assign({
|
|
8
|
+
// support customize accepts function
|
|
9
|
+
accepts() {
|
|
10
|
+
const fn = config.accepts || utils_1.accepts;
|
|
11
|
+
return fn(this);
|
|
12
|
+
},
|
|
13
|
+
/**
|
|
14
|
+
* default text error handler
|
|
15
|
+
* @param {Error} err
|
|
16
|
+
* @param ctx
|
|
17
|
+
*/
|
|
18
|
+
text(err, ctx) {
|
|
19
|
+
// unset all headers, and set those specified
|
|
20
|
+
ctx.res._headers = {};
|
|
21
|
+
ctx.set(err.headers);
|
|
22
|
+
if ((0, utils_1.isProduction)(app)) {
|
|
23
|
+
ctx.body = http.STATUS_CODES[ctx.status];
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
ctx.body = err.message;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* default html error handler
|
|
31
|
+
* @param {Error} err
|
|
32
|
+
*/
|
|
33
|
+
html(err, ctx) {
|
|
34
|
+
const status = (0, utils_1.detectStatus)(err);
|
|
35
|
+
if ((0, utils_1.isProduction)(app)) {
|
|
36
|
+
// 5xx
|
|
37
|
+
if (status >= 500) {
|
|
38
|
+
ctx.status = 500;
|
|
39
|
+
ctx.body = `<h2>Internal Server Error, real status: ${status}</h2>`;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// 4xx
|
|
44
|
+
ctx.status = status;
|
|
45
|
+
ctx.body = `<h2>${status} ${http.STATUS_CODES[status]}</h2>`;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// show simple error format for unittest
|
|
50
|
+
if (app.getEnv() === 'unittest' || app.getEnv() === 'test') {
|
|
51
|
+
ctx.status = status;
|
|
52
|
+
ctx.body = `${err.name}: ${err.message}\n${err.stack}`;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
ctx.body = utils_1.tpl
|
|
56
|
+
.replace('{{status}}', (0, utils_1.escapeHtml)(err.status))
|
|
57
|
+
.replace('{{stack}}', (0, utils_1.escapeHtml)(err.stack));
|
|
58
|
+
ctx.type = 'html';
|
|
59
|
+
},
|
|
60
|
+
/**
|
|
61
|
+
* default json error handler
|
|
62
|
+
* @param {Error} err
|
|
63
|
+
* @param ctx
|
|
64
|
+
*/
|
|
65
|
+
json(err, ctx) {
|
|
66
|
+
const status = (0, utils_1.detectStatus)(err);
|
|
67
|
+
const code = err.code || err.type;
|
|
68
|
+
if ((0, utils_1.isProduction)(app)) {
|
|
69
|
+
if (status >= 500) {
|
|
70
|
+
ctx.body = { code, message: http.STATUS_CODES[status] };
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
ctx.body = { code, message: err.message };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
ctx.body = { code, message: err.message, stack: err.stack };
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
}, config);
|
|
81
|
+
app.on('error', (err, ctx) => {
|
|
82
|
+
ctx = ctx || app.createAnonymousContext();
|
|
83
|
+
const status = (0, utils_1.detectStatus)(err);
|
|
84
|
+
// 5xx
|
|
85
|
+
if (status >= 500) {
|
|
86
|
+
try {
|
|
87
|
+
ctx.logger.error(err);
|
|
88
|
+
}
|
|
89
|
+
catch (ex) {
|
|
90
|
+
logger.error(err);
|
|
91
|
+
logger.error(ex);
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// 4xx
|
|
96
|
+
try {
|
|
97
|
+
ctx.logger.warn(err);
|
|
98
|
+
}
|
|
99
|
+
catch (ex) {
|
|
100
|
+
logger.warn(err);
|
|
101
|
+
logger.error(ex);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
app.context.onerror = function (err) {
|
|
105
|
+
// don't do anything if there is no error.
|
|
106
|
+
// this allows you to pass `this.onerror`
|
|
107
|
+
// to node-style callbacks.
|
|
108
|
+
if (err == null)
|
|
109
|
+
return;
|
|
110
|
+
// ignore all pedding request stream
|
|
111
|
+
if (this.req)
|
|
112
|
+
(0, utils_1.sendToWormhole)(this.req);
|
|
113
|
+
// wrap non-error object
|
|
114
|
+
if (!(err instanceof Error)) {
|
|
115
|
+
const newError = new Error('non-error thrown: ' + err);
|
|
116
|
+
// err maybe an object, try to copy the name, message and stack to the new error instance
|
|
117
|
+
if (err) {
|
|
118
|
+
if (err.name)
|
|
119
|
+
newError.name = err.name;
|
|
120
|
+
if (err.message)
|
|
121
|
+
newError.message = err.message;
|
|
122
|
+
if (err.stack)
|
|
123
|
+
newError.stack = err.stack;
|
|
124
|
+
if (err.status)
|
|
125
|
+
newError['status'] = err.status;
|
|
126
|
+
if (err.headers)
|
|
127
|
+
newError['headers'] = err.headers;
|
|
128
|
+
}
|
|
129
|
+
err = newError;
|
|
130
|
+
}
|
|
131
|
+
const headerSent = this.headerSent || !this.writable;
|
|
132
|
+
if (headerSent)
|
|
133
|
+
err.headerSent = true;
|
|
134
|
+
// delegate
|
|
135
|
+
app.emit('error', err, this);
|
|
136
|
+
// nothing we can do here other
|
|
137
|
+
// than delegate to the app-level
|
|
138
|
+
// handler and log.
|
|
139
|
+
if (headerSent)
|
|
140
|
+
return;
|
|
141
|
+
// ENOENT support
|
|
142
|
+
if (err.code === 'ENOENT')
|
|
143
|
+
err.status = 404;
|
|
144
|
+
if (typeof err.status !== 'number' || !http.STATUS_CODES[err.status]) {
|
|
145
|
+
err.status = 500;
|
|
146
|
+
}
|
|
147
|
+
this.status = err.status;
|
|
148
|
+
this.set(err.headers);
|
|
149
|
+
let type = 'text';
|
|
150
|
+
if (errorOptions.accepts) {
|
|
151
|
+
type = errorOptions.accepts.call(this, 'html', 'text', 'json');
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
type = this.accepts('html', 'text', 'json');
|
|
155
|
+
}
|
|
156
|
+
type = type || 'text';
|
|
157
|
+
if (errorOptions.all) {
|
|
158
|
+
errorOptions.all.call(this, err, this);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
if (errorOptions.redirect && type !== 'json') {
|
|
162
|
+
this.redirect(errorOptions.redirect);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
errorOptions[type].call(this, err, this);
|
|
166
|
+
this.type = type;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (type === 'json') {
|
|
170
|
+
this.body = JSON.stringify(this.body);
|
|
171
|
+
}
|
|
172
|
+
this.res.end(this.body);
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
exports.setupOnerror = setupOnerror;
|
|
176
|
+
//# sourceMappingURL=onerror.js.map
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function detectStatus(err: any): any;
|
|
2
|
+
export declare function accepts(ctx: any): "json" | "js" | "html";
|
|
3
|
+
export declare function sendToWormhole(stream: any): Promise<void>;
|
|
4
|
+
export declare function isProduction(app: any): boolean;
|
|
5
|
+
export declare const tpl = "\n<!DOCTYPE html>\n<html>\n <head>\n <title>Error - {{status}}</title>\n <meta name=\"viewport\" content=\"user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n <style>\n body {\n padding: 50px 80px;\n font: 14px \"Helvetica Neue\", Helvetica, sans-serif;\n }\n\n h1 {\n font-size: 2em;\n margin-bottom: 5px;\n }\n\n pre {\n font-size: .8em;\n }\n </style>\n </head>\n <body>\n <div id=\"error\">\n <h1>Error</h1>\n <p>Looks like something broke!</p>\n <pre>\n <code>\n{{stack}}\n </code>\n </pre>\n </div>\n </body>\n</html>";
|
|
6
|
+
/**
|
|
7
|
+
* Escape special characters in the given string of text.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} string The string to escape for inserting into HTML
|
|
10
|
+
* @return {string}
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export declare function escapeHtml(string: any): string;
|
|
14
|
+
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.escapeHtml = exports.tpl = exports.isProduction = exports.sendToWormhole = exports.accepts = exports.detectStatus = void 0;
|
|
4
|
+
function detectStatus(err) {
|
|
5
|
+
// detect status
|
|
6
|
+
let status = err.status || 500;
|
|
7
|
+
if (status < 200) {
|
|
8
|
+
// invalid status consider as 500, like urllib will return -1 status
|
|
9
|
+
status = 500;
|
|
10
|
+
}
|
|
11
|
+
return status;
|
|
12
|
+
}
|
|
13
|
+
exports.detectStatus = detectStatus;
|
|
14
|
+
function accepts(ctx) {
|
|
15
|
+
if (ctx.acceptJSON)
|
|
16
|
+
return 'json';
|
|
17
|
+
if (ctx.acceptJSONP)
|
|
18
|
+
return 'js';
|
|
19
|
+
return 'html';
|
|
20
|
+
}
|
|
21
|
+
exports.accepts = accepts;
|
|
22
|
+
function sendToWormhole(stream) {
|
|
23
|
+
return new Promise(resolve => {
|
|
24
|
+
if (typeof stream.resume !== 'function') {
|
|
25
|
+
return resolve();
|
|
26
|
+
}
|
|
27
|
+
// unpipe it
|
|
28
|
+
stream.unpipe && stream.unpipe();
|
|
29
|
+
// enable resume first
|
|
30
|
+
stream.resume();
|
|
31
|
+
if (stream._readableState && stream._readableState.ended) {
|
|
32
|
+
return resolve();
|
|
33
|
+
}
|
|
34
|
+
if (!stream.readable || stream.destroyed) {
|
|
35
|
+
return resolve();
|
|
36
|
+
}
|
|
37
|
+
function cleanup() {
|
|
38
|
+
stream.removeListener('end', onEnd);
|
|
39
|
+
stream.removeListener('close', onEnd);
|
|
40
|
+
stream.removeListener('error', onError);
|
|
41
|
+
}
|
|
42
|
+
function onEnd() {
|
|
43
|
+
cleanup();
|
|
44
|
+
resolve();
|
|
45
|
+
}
|
|
46
|
+
function onError() {
|
|
47
|
+
cleanup();
|
|
48
|
+
resolve();
|
|
49
|
+
}
|
|
50
|
+
stream.on('end', onEnd);
|
|
51
|
+
stream.on('close', onEnd);
|
|
52
|
+
stream.on('error', onError);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
exports.sendToWormhole = sendToWormhole;
|
|
56
|
+
function isProduction(app) {
|
|
57
|
+
return app.getEnv() !== 'local' && app.getEnv() !== 'unittest';
|
|
58
|
+
}
|
|
59
|
+
exports.isProduction = isProduction;
|
|
60
|
+
exports.tpl = `
|
|
61
|
+
<!DOCTYPE html>
|
|
62
|
+
<html>
|
|
63
|
+
<head>
|
|
64
|
+
<title>Error - {{status}}</title>
|
|
65
|
+
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
|
66
|
+
|
|
67
|
+
<style>
|
|
68
|
+
body {
|
|
69
|
+
padding: 50px 80px;
|
|
70
|
+
font: 14px "Helvetica Neue", Helvetica, sans-serif;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
h1 {
|
|
74
|
+
font-size: 2em;
|
|
75
|
+
margin-bottom: 5px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
pre {
|
|
79
|
+
font-size: .8em;
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
82
|
+
</head>
|
|
83
|
+
<body>
|
|
84
|
+
<div id="error">
|
|
85
|
+
<h1>Error</h1>
|
|
86
|
+
<p>Looks like something broke!</p>
|
|
87
|
+
<pre>
|
|
88
|
+
<code>
|
|
89
|
+
{{stack}}
|
|
90
|
+
</code>
|
|
91
|
+
</pre>
|
|
92
|
+
</div>
|
|
93
|
+
</body>
|
|
94
|
+
</html>`;
|
|
95
|
+
const matchHtmlRegExp = /["'&<>]/;
|
|
96
|
+
/**
|
|
97
|
+
* Escape special characters in the given string of text.
|
|
98
|
+
*
|
|
99
|
+
* @param {string} string The string to escape for inserting into HTML
|
|
100
|
+
* @return {string}
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
103
|
+
function escapeHtml(string) {
|
|
104
|
+
const str = '' + string;
|
|
105
|
+
const match = matchHtmlRegExp.exec(str);
|
|
106
|
+
if (!match) {
|
|
107
|
+
return str;
|
|
108
|
+
}
|
|
109
|
+
let escape;
|
|
110
|
+
let html = '';
|
|
111
|
+
let index = 0;
|
|
112
|
+
let lastIndex = 0;
|
|
113
|
+
for (index = match.index; index < str.length; index++) {
|
|
114
|
+
switch (str.charCodeAt(index)) {
|
|
115
|
+
case 34: // "
|
|
116
|
+
escape = '"';
|
|
117
|
+
break;
|
|
118
|
+
case 38: // &
|
|
119
|
+
escape = '&';
|
|
120
|
+
break;
|
|
121
|
+
case 39: // '
|
|
122
|
+
escape = ''';
|
|
123
|
+
break;
|
|
124
|
+
case 60: // <
|
|
125
|
+
escape = '<';
|
|
126
|
+
break;
|
|
127
|
+
case 62: // >
|
|
128
|
+
escape = '>';
|
|
129
|
+
break;
|
|
130
|
+
default:
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (lastIndex !== index) {
|
|
134
|
+
html += str.substring(lastIndex, index);
|
|
135
|
+
}
|
|
136
|
+
lastIndex = index + 1;
|
|
137
|
+
html += escape;
|
|
138
|
+
}
|
|
139
|
+
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
|
|
140
|
+
}
|
|
141
|
+
exports.escapeHtml = escapeHtml;
|
|
142
|
+
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midwayjs/koa",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Midway Web Framework for KOA",
|
|
5
5
|
"main": "dist/index",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc",
|
|
9
|
-
"test": "node --require=ts-node/register ../../node_modules/.bin/jest",
|
|
10
|
-
"cov": "node --require=ts-node/register ../../node_modules/.bin/jest --coverage --forceExit",
|
|
9
|
+
"test": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand",
|
|
10
|
+
"cov": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand --coverage --forceExit",
|
|
11
11
|
"ci": "npm run test"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
@@ -23,21 +23,20 @@
|
|
|
23
23
|
],
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@midwayjs/decorator": "^3.0.0
|
|
27
|
-
"@midwayjs/
|
|
28
|
-
"@midwayjs/
|
|
29
|
-
"@types/koa": "
|
|
30
|
-
"@types/koa-router": "
|
|
31
|
-
"fs-extra": "
|
|
32
|
-
"koa-bodyparser": "^4.3.0",
|
|
33
|
-
"koa-qs": "^3.0.0"
|
|
26
|
+
"@midwayjs/decorator": "^3.0.0",
|
|
27
|
+
"@midwayjs/logger": "2.14.0",
|
|
28
|
+
"@midwayjs/mock": "^3.0.0",
|
|
29
|
+
"@types/koa": "2.13.4",
|
|
30
|
+
"@types/koa-router": "7.4.4",
|
|
31
|
+
"fs-extra": "10.0.0"
|
|
34
32
|
},
|
|
35
33
|
"dependencies": {
|
|
36
34
|
"@koa/router": "^10.0.0",
|
|
37
|
-
"@midwayjs/
|
|
38
|
-
"@midwayjs/
|
|
39
|
-
"
|
|
40
|
-
"koa
|
|
35
|
+
"@midwayjs/cookies": "1.0.1",
|
|
36
|
+
"@midwayjs/core": "^3.0.0",
|
|
37
|
+
"@midwayjs/session": "^3.0.0",
|
|
38
|
+
"koa": "2.13.4",
|
|
39
|
+
"koa-bodyparser": "4.3.0"
|
|
41
40
|
},
|
|
42
41
|
"author": "Harry Chen <czy88840616@gmail.com>",
|
|
43
42
|
"repository": {
|
|
@@ -47,5 +46,5 @@
|
|
|
47
46
|
"engines": {
|
|
48
47
|
"node": ">=12"
|
|
49
48
|
},
|
|
50
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "55c26029bccf7bbb739fa1597e8f418dafa2caa0"
|
|
51
50
|
}
|