deth
Version:
Ethereum node focused on Developer Experience
87 lines (86 loc) • 2.29 kB
JavaScript
import { PathReporter } from 'io-ts/lib/PathReporter';
export const errorHandler = function (err, req, res, next) {
let httpError;
if (err instanceof IOTSError) {
httpError = new BadRequestHttpError(err.details);
}
else if (err instanceof HttpError) {
httpError = err;
}
else {
httpError = new InternalHttpError();
}
if (httpError instanceof InternalHttpError) {
console.error('Internal error occured: ', err);
}
console.error(`<-- ERROR: ${httpError.code} - ${httpError.message} (${httpError.details})`);
const isRPC = req.method === 'POST' && req.url === '/';
if (isRPC) {
res.status(httpError.code);
res.json(httpErrorToRpcErrorPayload(req, httpError));
}
else {
res.status(httpError.code);
res.json(httpError.toBody());
}
};
export class IOTSError extends Error {
constructor(details) {
super('IO-TS error');
this.details = PathReporter.report(details);
}
}
export class HttpError extends Error {
constructor(code, msg, details) {
super(msg);
this.code = code;
this.details = details;
}
toBody() {
return {
error: {
status: this.code,
message: this.message,
details: this.details,
},
};
}
}
export class BadRequestHttpError extends HttpError {
constructor(details) {
super(400, 'BadRequest', details);
}
}
export class NotFoundHttpError extends HttpError {
constructor(details = []) {
super(404, 'NotFound');
this.details = details;
}
}
export class InternalHttpError extends HttpError {
constructor() {
super(500, 'Internal');
}
}
function httpErrorToRpcStatus(err) {
switch (err.code) {
case 400:
return -32600;
case 404:
return -32601;
default:
return -32603;
}
}
function httpErrorToRpcErrorPayload(req, err) {
var _a;
return {
jsonrpc: '2.0',
id: (_a = req.body.id, (_a !== null && _a !== void 0 ? _a : null)),
error: {
code: httpErrorToRpcStatus(err),
message: err.message,
details: err.details,
},
};
}