快速错误处理在 Nuxt.js serverMiddleware 中不起作用

Express error handling not working in Nuxt.js serverMiddleware

我正在使用 Express (v4.17) 在 Nuxt.js (v2.15) 项目的 serverMiddleware 目录中构建后端。

我目前正在尝试在我的 API 路由中实施错误处理,特别是针对输入验证错误。 Express 有一个内置的默认错误处理程序,如 the docs:

中所述

If you pass an error to next() and you do not handle it in a custom error handler, it will be handled by the built-in error handler; the error will be written to the client with the stack trace. The stack trace is not included in the production environment.

When an error is written, the following information is added to the response:

  • The res.statusCode is set from err.status (or err.statusCode). If this value is outside the 4xx or 5xx range, it will be set to 500.

然后我创建了一个自定义错误 class:

// serverMiddleware/errors.js

class HTTPError extends Error {
  constructor (status) {
    super()
    this.status = status
  }
}

export class BadRequestError extends HTTPError {
  constructor () {
    super(400)
  }
}

我在我的路线中使用这个错误是这样的:

// serverMiddleware/index.js

import express from "express"
import { BadRequestError } from "./errors.js"

const app = express()

app.get("/", async (req, res, next) => {
  try {
    // validate req
    if (typeof req.query.foo !== "string") throw new BadRequestError()

    res.sendStatus(200)
  } catch (error) {
    next(error)
  }
})

export default app

如果我提供 foo 查询 属性,我会得到预期的 200 OK。但是,如果我不提供 foo,我希望得到 400 Bad Request 但我得到的是 500 Runtime Error。堆栈跟踪指向抛出 BadRequestError 的行。

当 运行 在没有 Nuxt.js 的独立 Express-only 项目中使用 app.listen(...) 而不是 export default app 完全相同的代码时,我得到 400 Bad Request 符合预期。

为了进一步测试这一点,我创建了一个自定义错误处理函数来覆盖 Express 的默认值,并将其添加到路由和导出之间:

// serverMiddleware/index.js

app.get(...)

app.use((err, req, res, next) => {
  console.error(err)
  res.status(err.status || 500).send("Something broke!")
})

export default app

连这个函数都达不到。我收到 500 响应,没有记录任何错误或“出现故障!”信息。它仍然只是一个指向抛出的堆栈跟踪。

同样,当在一个独立的 Express 项目中使用这个完全相同的错误处理函数时,我得到了正确的 400 响应“有些东西坏了!”留言.

这显然是 Nuxt.js 服务器中间件的问题,因为在非 Nuxt 项目中一切都按预期工作。

内置错误处理程序设置 res.statusCode,但它还会调用 next(error) 进一步传播错误。如果像你这样的 serverMiddleware 以这样的 next(error) 结尾,Nuxt.js 会拦截它并呈现一个错误页面(状态为 500,内容类型为 text/html)。

要避免这种情况,请创建您自己的“最终错误处理程序”,例如

export default function (err, req, res, next) {
  if (err.status) res.statusCode = err.status;
  res.setHeader("content-type", "application/json");
  res.end(JSON.stringify(err));
};

并将其包含在 nuxt.config.js 中的其他中间件之后:

export default {
  serverMiddleware: [
    "~/serverMiddleware/index",
    "~/serverMiddleware/final_error_handler"
  ]
};