なにが起こったか?
app.use((
// eslint-disable-next-line @typescript-eslint/no-explicit-any
err: any,
req: express.Request,
res: express.Response<BaseResponse.BaseApiResponse<{}>>,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
next: any
) => {
SentryLib.captureException(err)
LoggerLib.debug(`${err}`)
res.status(500).json({
data: {},
error: { message: 'standard error', code: 'ServerError' },
})
next()
})
export default class Controller {
/**
*
* @param {express.Request} req
* @param {express.Response} res
*/
public static async get(
req: express.Request<
{},
AreaPublicApiResponse.GetApiResponse,
any,
{}
>,
res: express.Response,
next: express.NextFunction
) {
throw Error('エラーですよ')
}
}
上記のようにデフォルトエラーハンドリングの実装を行っていて、APIで強制的にエラーを出すように設定してみたがデフォルトのエラーハンドリングが機能しない
公式を確認してみる
https://expressjs.com/ja/guide/error-handling.html
app.get('/', (req, res, next) => {
setTimeout(() => {
try {
throw new Error('BROKEN')
} catch (err) {
next(err)
}
}, 100)
})
nextを実行しないとどうやらデフォルトハンドリングまで行ってくれないらしい
Railsに慣れちゃってたので、エラーが起きたら自動的に検知してくれると勘違いしていた
修正版
export default class Controller {
/**
*
* @param {express.Request} req
* @param {express.Response} res
*/
public static async get(
req: express.Request<
{},
AreaPublicApiResponse.GetApiResponse,
any,
{}
>,
res: express.Response,
next: express.NextFunction
) {
try {
throw Error('エラーですよ')
} catch (e) {
next(e) // nextを実行
}
}
}
無事動くようになりました!
nextが呼ばれないとどうなるか
If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.
An Express application can use the following types of middleware:
ref: https://expressjs.com/en/guide/using-middleware.html
リクエストが滞留してしまうということが書かれている
同期的なエラーはExpressでデフォルトでハンドリングしてくれるが、非同期関数で発生するエラーはハンドリングしてくれないので、リクエストが滞留してしまいサーバーダウンの原因にもなってしまう恐れも
Express v 5.xでは非同期関数のエラーも自動でnext()が呼ばれるようになる
Starting with Express 5, route handlers and middleware that return a Promise will call next(value) automatically when they reject or throw an error. For example: