(err, req, res, next)
| 35 | * accepts it as an argument; it is expected to be mounted last. |
| 36 | */ |
| 37 | export const errorHandler: express.ErrorRequestHandler = async (err, req, res, next) => { |
| 38 | let statusCode = 500 |
| 39 | |
| 40 | if (errorHasStatusCode(err)) { |
| 41 | statusCode = err.statusCode |
| 42 | } else if (errorHasCode(err) && notFoundCodes.includes(err.code)) { |
| 43 | statusCode = HttpCode.NotFound |
| 44 | } |
| 45 | |
| 46 | res.status(statusCode) |
| 47 | |
| 48 | // Assume anything that explicitly accepts text/html is a user browsing a |
| 49 | // page (as opposed to an xhr request). Don't use `req.accepts()` since |
| 50 | // *every* request that I've seen (in Firefox and Chromium at least) |
| 51 | // includes `*/*` making it always truthy. Even for css/javascript. |
| 52 | if (req.headers.accept && req.headers.accept.includes("text/html")) { |
| 53 | const resourcePath = path.resolve(rootPath, "src/browser/pages/error.html") |
| 54 | res.set("Content-Type", getMediaMime(resourcePath)) |
| 55 | const content = await fs.readFile(resourcePath, "utf8") |
| 56 | res.send( |
| 57 | replaceTemplates(req, content) |
| 58 | .replace(/{{ERROR_TITLE}}/g, statusCode.toString()) |
| 59 | .replace(/{{ERROR_HEADER}}/g, statusCode.toString()) |
| 60 | .replace(/{{ERROR_BODY}}/g, escapeHtml(err.message)) |
| 61 | .replace(/{{APP_NAME}}/g, req.args["app-name"]), |
| 62 | ) |
| 63 | } else { |
| 64 | res.json({ |
| 65 | error: err.message, |
| 66 | ...(err.details || {}), |
| 67 | }) |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | /** |
| 72 | * Final WebSocket error handler. |
no test coverage detected