[RFC] 应用自定义 4xx 和 5xx 的方案
- Dominant language
- TypeScript
- Stars
- 19k
- Forks
- 1.8k
- PR merge metrics
- No merged PRs in 30d
Description
Updated: 最新的提案看下面 @popomore 的回复: https://github.com/eggjs/egg/issues/1086#issuecomment-413840182
--
## 目标
让应用自身可以定制这些特殊响应的功能,而不是通过 302 跳转到其他地方。
### 兼容性原则
如果应用没有开启此功能,则保持原来的是否方式不变化。
### notfound 中间件 throw 404 error
将 notfound 的逻辑也统一到 egg-onerror 来处理。
```js
this.throw(404);
```
### 应用通过 `app/onerror.js` 来配置自定义的处理逻辑
框架和应用都可以覆盖 `app/onerror.js` 来实现统一处理逻辑。
- 优先选择准确的 status handler
- 找不到就找 4xx,5xx 这种通用 handler
- 如果有 all,优先使用 all,否则根据 accepts 判断来选择 html,json
- 都找不到就找全局默认 onerror 处理
```js
// app/onerror.js
module.exports = app => {
return {
'404': {
* html(ctx, err) {
// 这里可以使用 render
yield ctx.render('404.html');
},
* json(ctx, err) {
// 不处理或者不配置或者返回 null, undefined,都会使用默认的 json 逻辑来处理
},
},
'403': function* (ctx, err) {
// all 的精简版本写法
},
'4xx': {
* all(ctx, err) {
// all 不区分 accepts,由开发者自行处理
},
},
'500': {
* html(ctx, err) {
},
* json(ctx, err) {
},
},
'5xx': {
* html(ctx, err) {
},
* json(ctx, err) {
},
},
};
};
```
简写方式
```js
// app/onerror.js
module.exports = {
'404': {
* html(ctx, err) {
// 这里可以使用 render
yield ctx.render('404.html');
},
* json(ctx, err) {
// 不处理或者不配置或者返回 null, undefined,都会使用默认的 json 逻辑来处理
},
},
'403': function* (ctx, err) {
// all 的精简版本写法
},
'4xx': {
* all(ctx, err) {
// all 不区分 accepts,由开发者自行处理
},
},
};
```
不分状态码的统一 handler
```js
// app/onerror.js
module.exports = {
'404': {
* html(ctx, err) {
// 这里可以使用 render
yield ctx.render('404.html');
},
* json(ctx, err) {
// 不处理或者不配置或者返回 null, undefined,都会使用默认的 json 逻辑来处理
},
},
'403': function* (ctx, err) {
// all 的精简版本写法
},
'4xx': {
* all(ctx, err) {
// all 不区分 accepts,由开发者自行处理
},
},
};
```
### 支持 async function
```js
// app/onerror.js
module.exports = function* all(ctx, err, status) {
// all 不区分 accepts 和 status,由开发者自行处理
};
```
### 支持标准 Controller 的方式
> 这里只是扩展联想,API 没想好怎样设计
```js
// app/onerror.js
module.exports = app => {
class ErrorController extends app.Controller {
* all(err, status) {
}
// 或者 async function 统一支持
async all(err, status) {
}
}
return ErrorController;
};
```
Contributor guide
Assessment
This issue has not been assessed yet.