错误处理
¥Error handling
Strapi 本身就以标准格式处理错误。
¥Strapi is natively handling errors with a standard format.
错误处理有 2 个用例:
¥There are 2 use cases for error handling:
作为通过 REST 或 GraphQL API 查询内容的开发者,你可能会 接收错误 来响应请求。
¥As a developer querying content through the REST or GraphQL APIs, you might receive errors in response to the requests.
作为自定义 Strapi 应用后端的开发者,你可以使用 抛出错误 的控制器和服务。
¥As a developer customizing the backend of your Strapi application, you could use controllers and services to throw errors.
接收错误
¥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 引发的错误包含在具有以下格式的 response 中:
¥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 引发的错误包含在具有以下格式的 response 中:
¥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 开发任何自定义逻辑时抛出错误的推荐方法是让 controller 或 中间件 以正确的状态和正文进行响应。
¥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 错误文档 中列出了可用的错误函数,但它们的名称应采用小驼峰式,以便 Strapi 使用(例如 badRequest
)。
¥This can be done by calling an error function on the context (i.e. ctx
). Available error functions are listed in the http-errors documentation but their name should be lower camel-cased to be used by Strapi (e.g. badRequest
).
错误函数接受 2 个参数,对应于开发者查询 API 的 error.message
和 error.details
属性 received:
¥Error functions accept 2 parameters that correspond to the error.message
and error.details
attributes received by a developer querying the API:
该函数的第一个参数是错误
message
¥the first parameter of the function is the error
message
第二个是将在收到的响应中设置为
details
的对象¥and the second one is the object that will be set as
details
in the response received
- JavaScript
- TypeScript
// 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();
}
// path: ./src/api/[api-name]/controllers/my-controller.ts
export default {
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.ts
export default 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
一旦你在比控制器或中间件更深的层上工作,就会有专用的错误类可用于引发错误。这些类是 节点 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.
有关 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:
- JavaScript
- TypeScript
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 ApplicationError('Something went wrong', { foo: 'bar' });
}
const result = await super.create(params);
return result;
}
});
import { errors } from '@strapi/utils';
import { factories } from '@strapi/strapi';
const { ApplicationError } = errors;
export default factories.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 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.
- JavaScript
- TypeScript
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 ApplicationError('Something went wrong', { foo: 'bar' });
}
},
};
import { errors } from '@strapi/utils';
const { ApplicationError } = errors;
export default {
beforeCreate(event) {
let okay = false;
// Throwing an error will prevent the entity from being created
if (!okay) {
throw new ApplicationError('Something went wrong', { foo: 'bar' });
}
},
};
政策
¥Policies
政策 是一种特殊类型的中间件,在控制器之前执行。它们用于检查用户是否被允许执行该操作。如果不允许用户执行该操作并且使用了 return false
,则将引发一般错误。作为替代方案,你可以使用来自 Strapi ForbiddenError
类、ApplicationError
类(请参阅 默认错误类别 的两个类)以及最后的 节点 Error
类 的嵌套类扩展来抛出自定义错误消息。
¥Policies are a special type of middleware that are executed before a controller. They are used to check if the user is allowed to perform the action or not. If the user is not allowed to perform the action and a return false
is used then a generic error will be thrown. As an alternative, you can throw a custom error message using a nested class extensions from the Strapi ForbiddenError
class, ApplicationError
class (see Default error classes for both classes), and finally the Node Error
class.
PolicyError
类可从 @strapi/utils
包中获取,并接受 2 个参数:
¥The PolicyError
class is available from @strapi/utils
package and accepts 2 parameters:
该函数的第一个参数是错误
message
¥the first parameter of the function is the error
message
(可选)第二个参数是将在收到的响应中设置为
details
的对象;最佳实践是使用引发错误的策略名称设置policy
键。¥(optional) the second parameter is the object that will be set as
details
in the response received; a best practice is to set apolicy
key with the name of the policy that threw the error.
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.
- JavaScript
- TypeScript
const { errors } = require('@strapi/utils');
const { PolicyError } = errors;
module.exports = (policyContext, config, { strapi }) => {
let isAllowed = false;
if (isAllowed) {
return true;
} else {
throw new PolicyError('You are not allowed to perform this action', {
policy: 'my-policy',
myCustomKey: 'myCustomValue',
});
}
}
import { errors } from '@strapi/utils';
const { PolicyError } = errors;
export default (policyContext, config, { strapi }) => {
let isAllowed = false;
if (isAllowed) {
return true;
} else {
throw new 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.
- Application
- Pagination
- NotFound
- Forbidden
- Unauthorized
- NotImplemented
- PayloadTooLarge
- Policy
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 ApplicationError('Something went wrong', { foo: 'bar' });
PaginationError
类是一个特定的错误类,通常在解析 REST、GraphQL 或 文档服务 的分页信息时使用。它接受以下参数:
¥The PaginationError
class is a specific error class that is typically used when parsing the pagination information from REST, GraphQL, or the Document Service. It accepts the following parameters:
范围 | 类型 | 描述 | 默认 |
---|---|---|---|
message | string | 错误信息 | Invalid pagination |
throw new PaginationError('Exceeded maximum pageSize limit');
NotFoundError
类是用于抛出 404
状态代码错误的通用错误类。它接受以下参数:
¥The NotFoundError
class is a generic error class for throwing 404
status code errors. It accepts the following parameters:
范围 | 类型 | 描述 | 默认 |
---|---|---|---|
message | string | 错误信息 | Entity not found |
throw new NotFoundError('These are not the droids you are looking for');
ForbiddenError
类是当用户未提供任何或正确的身份验证凭据时使用的特定错误类。它接受以下参数:
¥The ForbiddenError
class is a specific error class used when a user either doesn't provide any or the correct authentication credentials. It accepts the following parameters:
范围 | 类型 | 描述 | 默认 |
---|---|---|---|
message | string | 错误信息 | Forbidden access |
throw new ForbiddenError('Ah ah ah, you didn\'t say the magic word');
UnauthorizedError
类是当用户没有适当的角色或权限来执行特定操作但已正确验证时使用的特定错误类。它接受以下参数:
¥The UnauthorizedError
class is a specific error class used when a user doesn't have the proper role or permissions to perform a specific action, but has properly authenticated. It accepts the following parameters:
范围 | 类型 | 描述 | 默认 |
---|---|---|---|
message | string | 错误信息 | Unauthorized |
throw new UnauthorizedError('You shall not pass!');
NotImplementedError
类是传入请求尝试使用当前未实现或配置的功能时使用的特定错误类。它接受以下参数:
¥The NotImplementedError
class is a specific error class used when the incoming request is attempting to use a feature that is not currently implemented or configured. It accepts the following parameters:
范围 | 类型 | 描述 | 默认 |
---|---|---|---|
message | string | 错误信息 | This feature isn't implemented |
throw new NotImplementedError('This isn\'t implemented', { feature: 'test', implemented: false });
PayloadTooLargeError
类是当传入请求正文或附加文件超出服务器限制时使用的特定错误类。它接受以下参数:
¥The PayloadTooLargeError
class is a specific error class used when the incoming request body or attached files exceed the limits of the server. It accepts the following parameters:
范围 | 类型 | 描述 | 默认 |
---|---|---|---|
message | string | 错误信息 | Entity too large |
throw new PayloadTooLargeError('Uh oh, the file too big!');
PolicyError
类是设计用于与 路由政策 一起使用的特定错误。最佳实践建议是确保策略名称在 details
参数中传递。它接受以下参数:
¥The PolicyError
class is a specific error designed to be used with route policies. The best practice recommendation is to ensure the name of the policy is passed in the details
parameter. It accepts the following parameters:
范围 | 类型 | 描述 | 默认 |
---|---|---|---|
message | string | 错误信息 | Policy Failed |
details | object | 定义附加细节的对象 | {} |
throw new PolicyError('Something went wrong', { policy: 'my-policy' });