ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Sails 应用中的 500 错误页:views/500.ejs 的渲染机制与自定义指南

Sails 应用中的 500 错误页:views/500.ejs 的渲染机制与自定义指南 后端【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址https://gitcode.com/gh_mirrors/sa/sails点击查看免费下载导读views/500.ejs是 Sails 应用默认的「500: Server Error服务器内部错误」页面模板当应用抛出可捕获异常、或开发者显式调用res.serverError()时Sails 会依据客户端请求头是否Accept: text/html决定返回该 HTML 页面还是 JSON 响应。本文以 docs/anatomy/views/500.ejs.md 为核心骨架结合仓库内 responses 钩子、默认响应实现、默认 500 处理器与集成测试完整讲解该页面的触发时机、渲染调用链、错误数据流转含生产环境脱敏以及自定义改造方案帮助读者掌握 Sails 错误页面的全链路行为。一、views/500.ejs 在应用目录中的定位在 Sails 项目解剖Anatomy中views/目录存放应用全部自定义视图模板其入口说明位于 docs/anatomy/views/views.md若要创建自定义视图请在该目录下新建子目录与.ejs文件要让客户端能渲染它要么在config/routes.js中配置路由要么在控制器 action 中调用res.view()方法。views/500.ejs正是位于该目录下的特殊模板它不是由普通路由直接渲染而是被 Sails 的默认 500 处理器和res.serverError()响应方法在出错时自动选中的错误页。它的核心特征依据关联文档可以概括为三点面向 HTML 客户端不 Accept HTML 的客户端如 API 调用方、curl 未带Accept头、前端 XHR 等会收到 JSON 版本响应而非本页面自动触发应用抛出可捕获错误注意不是在异步回调内部抛出的错误时Sails 即认定请求进入 500: Server Error 状态并渲染该页手动触发在控制器或策略policy中执行return res.serverError( e );即可主动触发其中e为可选的 message、Error 对象或错误数组会被并入响应内容。二、什么时候会渲染 500.ejs触发路径全梳理2.1 自动触发默认 500 处理器Sails 为每个请求装配了默认的 500 与 404 处理器实现位于 lib/router/bindDefaultHandlers.js。其注释明确指出Default 500 and 404 handler. (defers to res.serverError() and res.notFound() whenever possible)也就是说当应用代码中抛出可捕获异常并被 Express 错误中间件链捕获时默认 500 处理器被触发它首先尝试调用res.serverError(err)见 bindDefaultHandlers.js// Next, try to use res.serverError(), if it exists and is valid. try { if (typeof res.serverError function) { return res.serverError(err); }//- } catch (unusedErr) { /* ... */ }res.serverError是 responses 钩子通过 shadow 路由注入到每个响应对象上的方法见 lib/hooks/responses/index.js其默认实现正是渲染views/500.ejs的核心。值得注意的是默认 500 处理器还内置了对 Express 特殊错误的判别bindDefaultHandlers.js如果错误是Error实例、其status 400且消息匹配Failed to decode param ...URL 参数解码失败则直接返回400 Bad request响应而不会进入 500 流程。若res.serverError不可用或调用失败处理器回退到兜底逻辑bindDefaultHandlers.js生产环境NODE_ENV productionres.sendStatus(500)不泄露任何错误细节非生产环境res.status(500).send(err)直接下发错误对象。2.2 手动触发res.serverError()在控制器、策略或自定义响应中可以随时显式触发 500 状态。关联文档给出的用法是return res.serverError( e );其中e是可选的 message、Error 对象或错误数组用于包含在响应内容中。当没有传参时res.serverError()同样可用。响应钩子注册的路由目标语法也支持在路由配置中直接绑定自定义响应例如post /foo: { response: ok }这种形式见 lib/hooks/responses/README.md同理也可以配置{ response: serverError }或自定义的 500 响应。2.3 关联视图的兄弟页views/404.ejsviews/404.ejs说明见 docs/anatomy/views/404.ejs.md与 500 页机制完全对称当用户请求的 URL 不匹配任何路由或 blueprint 时进入 404: Not Found 状态默认 404 处理器同样优先调用res.notFound()bindDefaultHandlers.js最终渲染views/404.ejs或返回 JSON。两者共同构成了 Sails 默认的错误响应页面体系。三、源码级剖析res.serverError() 如何渲染 500.ejsres.serverError的默认实现位于 lib/hooks/responses/defaults/serverError.js其执行流程可以拆解为以下关键步骤3.1 记录错误日志// Log error to console if (data ! undefined) { sails.log.error(Sending 500 (Server Error) response: \n, flaverr.parseError(data) || data); }通过sails.log.error输出错误详情flaverr.parseError用于从错误对象中提取可读信息。3.2 生产环境脱敏// Dont output error data with response in production. var dontRevealErrorInResponse process.env.NODE_ENV production; if (dontRevealErrorInResponse) { data undefined; }这是安全关键行为当NODE_ENV为production时传入res.serverError(err)的错误对象会被清空绝不会把堆栈或内部错误信息写入响应体。3.3 内容协商HTML 还是 JSON// Set status code res.status(500); // If appropriate, serve data as JSON. if (req.wantsJSON || !res.view) { // If no data was provided, use res.sendStatus(). if (data undefined) { return res.sendStatus(500); } // ... return res.json(data); }当req.wantsJSON为真客户端期望 JSON例如 API 请求或当前响应对象没有res.view方法视图钩子未启用时直接返回 JSON无数据则res.sendStatus(500)若数据是 Error 实例且没有自定义toJSON则改用err.stack返回避免res.json()将 Error 序列化成空对象否则进入 HTML 分支渲染views/500.ejs。3.4 渲染 500.ejs 及回退return res.view(500, { error: data }, function (err, html) { // If a view error occured, fall back to JSON. if (err) { // If the view was missing, ignore the error but provide a verbose log. if (err.code E_VIEW_FAILED) { sails.log.verbose(res.serverError() :: Could not locate view for error page ...); } // Otherwise ... log to the console with the details. else { sails.log.warn(res.serverError() :: When attempting to render error page view, ...); } return res.json(data); } return res.send(html); });这里向视图模板500即views/500.ejs传入一个名为error的本地变量值为经过脱敏处理后的data模板中即可通过% error %等 EJS 语法输出错误信息。若视图文件缺失E_VIEW_FAILED或渲染出错则自动回退到 JSON 响应保证客户端始终能收到格式正确的响应。四、res.view() 的底层渲染机制res.view()是res.render()的增强版本由视图钩子挂载实现见 lib/hooks/views/res.view.js。当res.serverError()调用res.view(500, { error: data }, cb)时其内部会依次完成推断视图路径未显式指定路径时根据req.options.action推断形如foo/bar此处直接使用显式路径500res.view.js合并 locals将req.options.locals、sails.config.views.locals与传入的 locals 按优先级合并res.view.js布局layout解析默认 EJS 引擎下支持sails.config.views.layout配置的布局模板布局通过ejs-locals机制生效res.view.js注入视图元数据向res.locals.view注入path、absPath、ext等元信息非生产环境下还会通过__dirname本地变量暴露模板绝对路径res.view.js调用底层res.render()编译模板渲染失败时设置E_VIEW_FAILED错误并调用res.serverError(err)兜底res.view.js。对于需要在服务端直接产出 HTML 字符串如发送邮件的场景还可使用sails.renderView()实现见 lib/hooks/views/render.js它与res.view共享同一套模板解析逻辑含布局处理、view元数据、i18n 国际化等。五、集成测试如何验证 500 行为仓库在 test/integration/middleware.500.test.js 中为 500 处理器编写了完整的行为测试可作为理解触发语义的第一手依据场景一默认 500 处理器无自定义中间件。测试首先写入自定义的views/500.ejs内容bogus err bruh!并配置路由/err: function (req, res) { throw new Error(errrr); }然后发起带Accept: text/html的 GET 请求断言assert.equal(response.statusCode, 500); assert(body.match(html)); assert(body.match(bogus err bruh!));这证实了「应用抛出可捕获异常 → 默认 500 处理器 → 渲染 500.ejs → 返回 500 状态码的 HTML 页面」的完整链路也证明自定义的 500.ejs 内容会被原样渲染进响应体。场景二自定义 500 中间件。通过在sails.config.http.middleware.order中追加err并实现err: function (err, req, res, next) { return res.send(custom err bro); }可以完全接管错误处理此时请求返回 200 与自定义文案——说明 500 处理器是可替换的 HTTP 中间件。场景三从中间件顺序中移除500。当自定义order中不再包含500时默认 500 处理器仍会被重新装配见 lib/hooks/http/initialize.js 中_.contains([handleBodyParserError, startRequestTimer, 404, 500], middleware)的检查逻辑因此测试三断言默认处理器依然生效。六、自定义 500 错误页面的完整方案6.1 方案 A直接编辑 views/500.ejs最直接的方式是改写模板文件本身。默认渲染调用res.view(500, { error: data }, cb)传入error本地变量因此在模板中可以直接引用!-- views/500.ejs -- h1服务器开小差了500/h1 % if (typeof error ! undefined error) { % p错误详情仅开发环境可见% error.message || error %/p % } % a href/返回首页/a注意生产环境下由于data已被置为undefined见 3.2 节脱敏逻辑error变量在模板中会是undefined需要像上面这样做存在性判断避免模板报错。6.2 方案 B自定义响应文件 api/responses/serverError.jsSails 会加载应用api/responses/目录下的自定义响应并覆盖内置默认实现见 lib/hooks/responses/index.js内置默认集包含ok、negotiate、notFound、serverError、forbidden、badRequest。将仓库内置实现 lib/hooks/responses/defaults/serverError.js 复制到api/responses/serverError.js后按需修改即可在保持既有渲染链路的前提下调整日志、脱敏规则或视图路径例如渲染res.view(errors/500, ...)。需要特别注意的是自定义响应名不能与保留的res.*方法冲突保留键包括view、status、send、json、redirect等见 lib/hooks/responses/index.js否则会抛出invalidCustomResponse致命错误。6.3 方案 C自定义 HTTP 中间件接管错误处理对于需要全局统一错误响应如接入错误追踪平台、统一 JSON 错误结构的场景可通过config/http.js配置自定义 500 中间件测试二中已演示。Sails 也会在检测到sails.config.http.middleware[500]存在时跳过默认处理器见 lib/hooks/http/initialize.js。6.4 方案 D路由直接绑定自定义响应利用 responses 钩子支持的response路由目标语法见 lib/hooks/responses/README.md可以在config/routes.js中把指定路由直接绑定到某个响应方法module.exports.routes { post /some-fragile-endpoint: { response: serverError } };七、最佳实践与安全提醒生产环境永不泄露错误细节仓库内置实现已默认在生产环境清空error数据自定义模板时务必保持该语义不要在NODE_ENV production时输出堆栈或 SQL 语句为 500.ejs 提供通用降级由于视图缺失时res.serverError()会自动回退 JSON自定义错误页应保证模板语法健壮对error变量做空值判断保持Accept协商语义SPA/API 场景下客户端通常不会Accept: text/html会直接收到 JSON因此 500.ejs 主要服务于浏览器直达 URL 的用户异步回调中的错误不会被自动捕获关联文档明确指出「在异步回调内部抛出的错误」不构成 500 状态这类错误需要显式return res.serverError(e)或在回调边界手动处理结合 404 页统一设计views/404.ejs与views/500.ejs同属错误页体系详见 docs/anatomy/views/404.ejs.md 与 docs/anatomy/views/500.ejs.md建议保持视觉风格一致提供首页回退链接以改善用户体验。相关仓库路径速查关联文档docs/anatomy/views/500.ejs.md视图目录说明docs/anatomy/views/views.md404 页说明docs/anatomy/views/404.ejs.md默认 500 响应实现lib/hooks/responses/defaults/serverError.js默认 500/404 处理器lib/router/bindDefaultHandlers.js响应钩子自定义响应加载与挂载lib/hooks/responses/index.jsres.view() 实现lib/hooks/views/res.view.jssails.renderView() 实现lib/hooks/views/render.js500 行为集成测试test/integration/middleware.500.test.js500 响应 API 参考docs/reference/res/res.serverError.md赞分享后端【免费下载链接】sailsRealtime MVC Framework for Node.js项目地址https://gitcode.com/gh_mirrors/sa/sails点击查看免费下载相关推荐Sails 默认错误页面解析views/404.ejs 与 views/500.ejs 的触发机制、渲染逻辑与自定义方案Sails 默认错误页面解析views/404.ejs 与 views/500.ejs 的触发机制、渲染逻辑与自定义方案 views/404.ejs 与 vi后端Sails 实战指南深入理解 views/pages/homepage.ejs 与默认 EJS 视图渲染机制Sails 实战指南深入理解 views/pages/homepage.ejs 与默认 EJS 视图渲染机制 导读 本文以 SailsRealtime MV后端Next.js自定义错误页面404、500与边缘错误处理Next.js自定义错误页面404、500与边缘错误处理 在Web应用开发中错误处理是提升用户体验的关键环节。当用户访问不存在的页面、服务器发生异常或网络出前端后端Web框架SSR前端构建上一篇深入理解Pushup编译原理从.up文件到纯Go代码的转换过程下一篇终极Zerox OCR优化指南1000页PDF分块处理与内存控制完整方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表