Skip to content

[RFC] 应用自定义 4xx 和 5xx 的方案 #1086

@fengmk2

Description

@fengmk2

Updated: 最新的提案看下面 @popomore 的回复: #1086 (comment)

--

目标

让应用自身可以定制这些特殊响应的功能,而不是通过 302 跳转到其他地方。

兼容性原则

如果应用没有开启此功能,则保持原来的是否方式不变化。

notfound 中间件 throw 404 error

将 notfound 的逻辑也统一到 egg-onerror 来处理。

this.throw(404);

应用通过 app/onerror.js 来配置自定义的处理逻辑

框架和应用都可以覆盖 app/onerror.js 来实现统一处理逻辑。

  • 优先选择准确的 status handler
  • 找不到就找 4xx,5xx 这种通用 handler
    • 如果有 all,优先使用 all,否则根据 accepts 判断来选择 html,json
  • 都找不到就找全局默认 onerror 处理
// 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) {
      },
    },
  };
};

简写方式

  // 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

// 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

  // app/onerror.js
  module.exports = function* all(ctx, err, status) {
    // all 不区分 accepts 和 status,由开发者自行处理
  };

支持标准 Controller 的方式

这里只是扩展联想,API 没想好怎样设计

// app/onerror.js
module.exports = app => {
  class ErrorController extends app.Controller {
    * all(err, status) {

    }
    // 或者 async function 统一支持
    async all(err, status) {

    }
  }

  return ErrorController;
};

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions