Skip to main content

错误处理

🌐 Error handling

Page summary:

Strapi 的 API 会以一致的结构返回错误,并允许后端代码为控制器、服务、策略或生命周期抛出自定义异常。本档文档列出了错误类、上下文助手以及编写有意义响应的示例。

Strapi 本身就以标准格式处理错误。

🌐 Strapi is natively handling errors with a standard format.

错误处理有 2 个用例:

🌐 There are 2 use cases for error handling:

  • 作为通过 RESTGraphQL API 查询内容的开发者,你可能会在请求响应中 收到错误
  • 作为开发者在定制 Strapi 应用的后端时,你可以使用控制器和服务来抛出错误

收到错误

🌐 Receiving errors

错误包含在响应对象中,使用 error 键,并包括诸如 HTTP 状态码、错误名称及附加信息等信息。

🌐 Errors are included in the response object with the error key and include information such as the HTTP status code, the name of the error, and additional information.

REST 错误

🌐 REST errors

REST API 抛出的错误包含在具有以下格式的响应中:

🌐 Errors thrown by the REST API are included in the response that has the following format:

{
"data": null,
"error": {
"status": "", // HTTP status
"name": "", // Strapi error name ('ApplicationError' or 'ValidationError')
"message": "", // A human readable error message
"details": {
// error info specific to the error type
}
}
}

GraphQL 错误

🌐 GraphQL errors

GraphQL API 抛出的错误包含在具有以下格式的响应中:

🌐 Errors thrown by the GraphQL API are included in the response that has the following format:

{ "errors": [
{
"message": "", // A human reable error message
"extensions": {
"error": {
"name": "", // Strapi error name ('ApplicationError' or 'ValidationError'),
"message": "", // A human reable error message (same one as above);
"details": {}, // Error info specific to the error type
},
"code": "" // GraphQL error code (ex: BAD_USER_INPUT)
}
}
],
"data": {
"graphQLQueryName": null
}
}

抛出错误

🌐 Throwing errors


控制器和中间件

🌐 Controllers and middlewares

在使用 Strapi 开发任何自定义逻辑时,推荐的抛出错误的方式是让 controllermiddleware 返回正确的状态和主体。

🌐 The recommended way to throw errors when developing any custom logic with Strapi is to have the controller or middleware respond with the correct status and body.

这可以通过在上下文上调用错误函数来完成(即 ctx)。可用的错误函数列在 http-errors documentation 中,但它们的名称在 Strapi 中使用时应该是小驼峰命名(例如 badRequest)。

错误函数接受两个参数,它们对应开发者在查询 API 时接收到的 error.messageerror.details 属性 接收

🌐 Error functions accept 2 parameters that correspond to the error.message and error.details attributes received by a developer querying the API:

  • 函数的第一个参数是错误 message
  • 第二个是将在收到的响应中被设置为 details 的对象
// path: ./src/api/[api-name]/controllers/my-controller.js

module.exports = {
renameDog: async (ctx, next) => {
const newName = ctx.request.body.name;
if (!newName) {
return ctx.badRequest('name is missing', { foo: 'bar' })
}
ctx.body = strapi.service('api::dog.dog').rename(newName);
}
}

// path: ./src/api/[api-name]/middlewares/my-middleware.js

module.exports = async (ctx, next) => {
const newName = ctx.request.body.name;
if (!newName) {
return ctx.badRequest('name is missing', { foo: 'bar' })
}
await next();
}

服务和模型生命周期

🌐 Services and models lifecycles

一旦你在比控制器或中间件更深的层次工作,就有专门的错误类可以用来抛出错误。这些类是对 Node `Error` 类 的扩展,并且专门针对某些使用场景。

🌐 Once you are working at a deeper layer than the controllers or middlewares there are dedicated error classes that can be used to throw errors. These classes are extensions of Node `Error` class and are specifically targeted for certain use-cases.

这些错误类是通过 @strapi/utils 包导入的,可以从多个不同的层调用。以下示例使用服务层,但错误类不仅限于服务和模型生命周期。在模型生命周期层抛出错误时,建议使用 ApplicationError 类,以便在管理面板中显示适当的错误信息。

🌐 These error classes are imported through the @strapi/utils package and can be called from several different layers. The following examples use the service layer but error classes are not just limited to services and model lifecycles. When throwing errors in the model lifecycle layer, it's recommended to use the ApplicationError class so that proper error messages are shown in the admin panel.

Note

请参阅 默认错误类 部分,以获取有关 Strapi 提供的错误类的更多信息。

🌐 See the default error classes section for more information on the error classes provided by Strapi.

示例:在服务中抛出错误**

🌐 Example: Throwing an error in a service**

此示例展示了如何封装一个 核心服务 并对 create 方法进行自定义验证:

🌐 This example shows wrapping a core service and doing a custom validation on the create method:

path: ./src/api/restaurant/services/restaurant.js

const { errors } = require('@strapi/utils');
const { ApplicationError } = errors;
const { createCoreService } = require('@strapi/strapi').factories;

module.exports = createCoreService('api::restaurant.restaurant', ({ strapi }) => ({
async create(params) {
let okay = false;

// Throwing an error will prevent the restaurant from being created
if (!okay) {
throw new errors.ApplicationError('Something went wrong', { foo: 'bar' });
}

const result = await super.create(params);

return result;
}
});

示例:在模型生命周期中抛出错误**

🌐 Example: Throwing an error in a model lifecycle**

此示例展示了如何构建一个自定义模型生命周期并能够抛出一个错误,该错误会停止请求并将适当的错误信息返回给管理面板。通常你应该只在 beforeX 生命周期中抛出错误,而不是在 afterX 生命周期中抛出。

🌐 This example shows building a custom model lifecycle and being able to throw an error that stops the request and will return proper error messages to the admin panel. Generally you should only throw an error in beforeX lifecycles, not afterX lifecycles.

path: ./src/api/[api-name]/content-types/[api-name]/lifecycles.js

const { errors } = require('@strapi/utils');
const { ApplicationError } = errors;

module.exports = {
beforeCreate(event) {
let okay = false;

// Throwing an error will prevent the entity from being created
if (!okay) {
throw new errors.ApplicationError('Something went wrong', { foo: 'bar' });
}
},
};

政策

🌐 Policies

策略 是一种特殊类型的中间件,在控制器执行之前运行。它们用于检查用户是否被允许执行该操作。如果用户不被允许执行该操作并且使用了 return false,则会抛出通用错误。作为替代,你可以使用从 Strapi ForbiddenError 类、ApplicationError 类派生的嵌套类扩展来抛出自定义错误消息(请参阅 默认错误类 了解这两个类),最后还可以使用 Node `Error` 类

PolicyError 类可从 @strapi/utils 包中获得,并接受 2 个参数:

🌐 The PolicyError class is available from @strapi/utils package and accepts 2 parameters:

  • 函数的第一个参数是错误 message
  • (可选) 第二个参数是将被设置为响应中 details 的对象;一个最佳做法是设置一个 policy 键,其值为抛出错误的策略名称。

示例:在自定义策略中抛出 PolicyError

🌐 Example: Throwing a PolicyError in a custom policy

此示例展示了如何构建一个 自定义策略,该策略将抛出自定义错误消息并停止请求。

🌐 This example shows building a custom policy that will throw a custom error message and stop the request.

path: ./src/api/[api-name]/policies/my-policy.js

const { errors } = require('@strapi/utils');
const { PolicyError } = errors;

module.exports = (policyContext, config, { strapi }) => {
let isAllowed = false;

if (isAllowed) {
return true;
} else {
throw new errors.PolicyError('You are not allowed to perform this action', {
policy: 'my-policy',
myCustomKey: 'myCustomValue',
});
}
}

默认错误类

🌐 Default error classes

默认的错误类可以从 @strapi/utils 包中获得,并可以在你的代码中导入和使用。任何默认的错误类都可以被扩展以创建自定义错误类。然后,自定义错误类可以在你的代码中使用来抛出错误。

🌐 The default error classes are available from the @strapi/utils package and can be imported and used in your code. Any of the default error classes can be extended to create a custom error class. The custom error class can then be used in your code to throw errors.

ApplicationError 类是一个通用的应用错误类,通常推荐作为默认的错误类。该类专门设计用于抛出管理员面板可以读取并显示给用户的正确错误信息。它接受以下参数:

🌐 The ApplicationError class is a generic error class for application errors and is generally recommended as the default error class. This class is specifically designed to throw proper error messages that the admin panel can read and show to the user. It accepts the following parameters: | 参数 | 类型 | 描述 | 默认值 || --- | --- | --- | --- || message | string | 错误信息 | An application error occured || details | object | 定义额外细节的对象 | {} |

throw new errors.ApplicationError('Something went wrong', { foo: 'bar' });