자바스크립트에서 Error를 던져서 에러 처리하는 것은 쉽고 간단한 방법이다.
express에서도 마찬가지이다. Error를 던지면 200 OK가 아닌, 500 Internal Serval Error를 발생시킬 수 있다.
const express = require('express');
const app = express();
app.get('/', (req, res) => {
throw new Error('BadRequest');
});
app.listen(3000, () => {
console.log('listen');
});
const express = require('express');
const createError = require('http-errors');
const app = express();
app.get('/', (req, res) => {
throw new createError.BadRequest();
});
app.listen(3000, () => { console.log('listen') });
http-errors
를 쓰는 대신 에러 클래스를 직접 구현하고 싶은 생각이 들지 모른다.
에러 객체에 status
또는 statusCode
로 원하는 상태 코드를 넣어준다.
const express = require('express');
const app = express();
app.get('/', (req, res) => {
const e = new Error('sample');
e.status = 400;
throw e;
});
app.listen(3000, () => { console.log('listen') });
Error에 status, statusCode를 넣는건 자바스크립트 세상의 표준이 아니다. 그래서 많은 라이브러리의 에러 클래스에는 status, statusCode 속성이 없다.
export default function ValidationError(errors, value, field, type) {
this.name = 'ValidationError';
this.value = value;
this.path = field;
this.type = type;
this.errors = [];
this.inner = [];
// ...
this.message =
this.errors.length > 1
? `${this.errors.length} errors occurred`
: this.errors[0];
if (Error.captureStackTrace) Error.captureStackTrace(this, ValidationError);
}
위와 같은 라이브러리를 사용하는데 에러가 던져지면 어떻게 대응할까?
catch
를 통해서 라이브러리에서 던져진 에러를 잡은 후 http-errors
로 다시 던지는 것도 방법이다. 하지만 기존 코드를 전부 catch
로 감싸는 것은 너무 무모하다.
에러 핸들러에서 err.name
를 확인하고 원하는 에러를 대신 던지는 식으로 처리할 수 있다.
const express = require('express');
const createErrors = require('http-errors');
const jwt = require('jsonwebtoken');
const app = express();
app.get('/', (req, res) => {
throw new jwt.JsonWebTokenError('this is sample error');
});
const newErrorMap = new Map([
['JsonWebTokenError', createErrors.BadRequest],
['ValidationError', createErrors.BadRequest],
]);
app.use((err, req, res, next) => {
const newError = newErrorMap.get(err.name);
if (newError) {
next(new newError(err.message));
} else {
next(err);
}
});
app.listen(3000, () => { console.log('listen'); });