mirror of
https://github.com/directus/directus.git
synced 2026-01-30 10:48:00 -05:00
124 lines
2.6 KiB
TypeScript
124 lines
2.6 KiB
TypeScript
import { ErrorRequestHandler } from 'express';
|
|
import { ValidationError } from '@hapi/joi';
|
|
import { TokenExpiredError } from 'jsonwebtoken';
|
|
import logger from './logger';
|
|
|
|
export enum ErrorCode {
|
|
NOT_FOUND = 'NOT_FOUND',
|
|
FIELD_NOT_FOUND = 'FIELD_NOT_FOUND',
|
|
INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR',
|
|
ENOENT = 'ENOENT',
|
|
EXTENSION_ILLEGAL_TYPE = 'EXTENSION_ILLEGAL_TYPE',
|
|
INVALID_QUERY = 'INVALID_QUERY',
|
|
INVALID_USER_CREDENTIALS = 'INVALID_USER_CREDENTIALS',
|
|
USER_NOT_FOUND = 'USER_NOT_FOUND',
|
|
FAILED_VALIDATION = 'FAILED_VALIDATION',
|
|
MALFORMED_JSON = 'MALFORMED_JSON',
|
|
TOKEN_EXPIRED = 'TOKEN_EXPIRED',
|
|
TOO_MANY_ITEMS = 'TOO_MANY_ITEMS',
|
|
}
|
|
|
|
enum HTTPStatus {
|
|
NOT_FOUND = 404,
|
|
FIELD_NOT_FOUND = 400,
|
|
INTERNAL_SERVER_ERROR = 500,
|
|
ENOENT = 501,
|
|
EXTENSION_ILLEGAL_TYPE = 400,
|
|
INVALID_QUERY = 400,
|
|
INVALID_USER_CREDENTIALS = 401,
|
|
USER_NOT_FOUND = 401,
|
|
FAILED_VALIDATION = 422,
|
|
MALFORMED_JSON = 400,
|
|
TOKEN_EXPIRED = 401,
|
|
TOO_MANY_ITEMS = 400,
|
|
}
|
|
|
|
export const errorHandler: ErrorRequestHandler = (
|
|
error: APIError | ValidationError | Error,
|
|
req,
|
|
res,
|
|
next
|
|
) => {
|
|
let response: any = {};
|
|
|
|
if (error instanceof APIError) {
|
|
logger.debug(error);
|
|
|
|
res.status(error.status);
|
|
|
|
response = {
|
|
error: {
|
|
code: error.code,
|
|
message: error.message,
|
|
},
|
|
};
|
|
} else if (error instanceof ValidationError) {
|
|
logger.debug(error);
|
|
|
|
res.status(HTTPStatus.FAILED_VALIDATION);
|
|
|
|
response = {
|
|
error: {
|
|
code: ErrorCode.FAILED_VALIDATION,
|
|
message: error.message,
|
|
},
|
|
};
|
|
} else if (error instanceof TokenExpiredError) {
|
|
logger.debug(error);
|
|
res.status(HTTPStatus.TOKEN_EXPIRED);
|
|
response = {
|
|
error: {
|
|
code: ErrorCode.TOKEN_EXPIRED,
|
|
message: 'The provided token is expired.',
|
|
},
|
|
};
|
|
}
|
|
|
|
// Syntax errors are most likely thrown by Body Parser when misaligned JSON is sent to the API
|
|
else if (error instanceof SyntaxError && 'entity.parse.failed') {
|
|
logger.debug(error);
|
|
|
|
res.status(HTTPStatus.MALFORMED_JSON);
|
|
|
|
response = {
|
|
error: {
|
|
code: ErrorCode.MALFORMED_JSON,
|
|
message: error.message,
|
|
},
|
|
};
|
|
} else {
|
|
logger.error(error);
|
|
|
|
res.status(500);
|
|
|
|
response = {
|
|
error: {
|
|
code: ErrorCode.INTERNAL_SERVER_ERROR,
|
|
},
|
|
};
|
|
|
|
if (process.env.NODE_ENV === 'development') {
|
|
response.error.message = error.message;
|
|
}
|
|
}
|
|
|
|
if (process.env.NODE_ENV === 'development') {
|
|
response.error.stack = error.stack;
|
|
}
|
|
|
|
return res.json(response);
|
|
};
|
|
|
|
export default class APIError extends Error {
|
|
status: HTTPStatus;
|
|
code: ErrorCode;
|
|
|
|
constructor(code: ErrorCode, message: string) {
|
|
super(message);
|
|
this.status = HTTPStatus[code] || 500;
|
|
this.code = code;
|
|
|
|
Error.captureStackTrace(this, this.constructor);
|
|
}
|
|
}
|