@midwayjs/koa
Version:
Midway Web Framework for KOA
185 lines • 6.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupOnError = setupOnError;
const http = require("http");
const utils_1 = require("./utils");
const core_1 = require("@midwayjs/core");
function setupOnError(app, config, logger) {
const errorOptions = Object.assign({
// support customize accepts function
accepts() {
const fn = config.accepts || utils_1.accepts;
return fn(this);
},
/**
* default text error handler
* @param {Error} err
* @param ctx
*/
text(err, ctx) {
// unset all headers, and set those specified
ctx.res._headers = {};
ctx.set(err.headers);
if ((0, utils_1.isProduction)(app)) {
ctx.body = http.STATUS_CODES[ctx.status];
}
else {
ctx.body = err.message;
}
},
/**
* default html error handler
* @param {Error} err
*/
html(err, ctx) {
const status = (0, utils_1.detectStatus)(err);
if ((0, utils_1.isProduction)(app)) {
// 5xx
if (status >= 500) {
ctx.status = 500;
ctx.body = `<h2>Internal Server Error, real status: ${status}</h2>`;
return;
}
else {
// 4xx
ctx.status = status;
ctx.body = `<h2>${status} ${http.STATUS_CODES[status]}</h2>`;
return;
}
}
// show simple error format for unittest
if (app.getEnv() === 'unittest' || app.getEnv() === 'test') {
ctx.status = status;
ctx.body = `${err.name}: ${err.message}\n${err.stack}`;
return;
}
ctx.body = utils_1.tpl
.replace('{{status}}', (0, utils_1.escapeHtml)(err.status))
.replace('{{errorCode}}', (0, utils_1.escapeHtml)(err.code))
.replace('{{stack}}', (0, utils_1.escapeHtml)(err.stack));
ctx.type = 'html';
},
/**
* default json error handler
* @param {Error} err
* @param ctx
*/
json(err, ctx) {
const status = (0, utils_1.detectStatus)(err);
const code = err.code || err.type;
if ((0, utils_1.isProduction)(app)) {
if (status >= 500) {
ctx.body = { code, message: http.STATUS_CODES[status] };
}
else {
ctx.body = { code, message: err.message };
}
}
else {
ctx.body = { code, message: err.message, stack: err.stack };
}
},
}, config);
app.on('error', (err, ctx) => {
ctx = ctx || app.createAnonymousContext();
const status = (0, utils_1.detectStatus)(err);
// 5xx
if (status >= 500) {
try {
ctx.logger.error(err);
}
catch (ex) {
logger.error(err);
logger.error(ex);
}
return;
}
// 4xx
try {
ctx.logger.warn(err);
}
catch (ex) {
logger.warn(err);
logger.error(ex);
}
});
app.context.onerror = function (err) {
// don't do anything if there is no error.
// this allows you to pass `this.onerror`
// to node-style callbacks.
if (err == null)
return;
// ignore all pedding request stream
if (this.req)
(0, utils_1.sendToWormhole)(this.req);
// wrap non-error object
if (!(err instanceof Error)) {
let errMsg = err;
if (typeof err === 'object') {
try {
errMsg = core_1.Utils.safeStringify(err);
// eslint-disable-next-line no-empty
}
catch (e) { }
}
const newError = new Error('non-error thrown: ' + errMsg);
// err maybe an object, try to copy the name, message and stack to the new error instance
if (err) {
if (err.name)
newError.name = err.name;
if (err.message)
newError.message = err.message;
if (err.stack)
newError.stack = err.stack;
if (err.status)
newError['status'] = err.status;
if (err.headers)
newError['headers'] = err.headers;
}
err = newError;
}
const headerSent = this.headerSent || !this.writable;
if (headerSent)
err.headerSent = true;
// delegate
app.emit('error', err, this);
// nothing we can do here other
// than delegate to the app-level
// handler and log.
if (headerSent)
return;
// ENOENT support
if (err.code === 'ENOENT')
err.status = 404;
if (typeof err.status !== 'number' || !http.STATUS_CODES[err.status]) {
err.status = 500;
}
this.status = err.status;
this.set(err.headers);
let type;
if (errorOptions.accepts) {
type = errorOptions.accepts.call(this, 'html', 'text', 'json');
}
else {
type = this.accepts('html', 'text', 'json');
}
type = type || 'text';
if (errorOptions.all) {
errorOptions.all.call(this, err, this);
}
else {
if (errorOptions.redirect && type !== 'json') {
this.redirect(errorOptions.redirect);
}
else {
errorOptions[type].call(this, err, this);
this.type = type;
}
}
if (type === 'json') {
this.body = JSON.stringify(this.body);
}
this.res.end(this.body);
};
}
//# sourceMappingURL=onerror.js.map