GraphQL 插件
¥GraphQL plugin
默认情况下,Strapi 为你的每种内容类型创建 REST 端点。GraphQL 插件添加了一个 GraphQL 端点来获取和修改你的内容。安装 GraphQL 插件后,你可以使用基于 Apollo Server 的 GraphQL Sandbox 以交互方式构建查询和修改,并阅读针对你 的内容类型量身定制的文档。
¥By default Strapi create REST endpoints for each of your content-types. The GraphQL plugin adds a GraphQL endpoint to fetch and mutate your content. With the GraphQL plugin installed, you can use the Apollo Server-based GraphQL Sandbox to interactively build your queries and mutations and read documentation tailored to your content types.
位置:可通过管理面板使用。通过管理面板和服务器代码进行配置,具有不同的选项集。
包名称:@strapi/plugin-graphql
其他资源:Strapi 市场页面
¥ Location: Usable via the admin panel. Configured through both admin panel and server code, with different sets of options.
Package name: @strapi/plugin-graphql
Additional resources: Strapi Marketplace page


安装
¥Installation
要安装 GraphQL 插件,请在终端中运行以下命令:
¥To install the GraphQL plugin, run the following command in your terminal:
- Yarn
- NPM
yarn add @strapi/plugin-graphql
npm install @strapi/plugin-graphql
安装后,GraphQL 沙箱可通过 /graphql
URL 访问,并可用于以交互方式构建查询和修改并阅读针对你的内容类型量身定制的文档。
¥Once installed, the GraphQL sandbox is accessible at the /graphql
URL and can be used to interactively build your queries and mutations and read documentation tailored to your content-types.
安装插件后,当你的 Strapi 应用服务器运行时,可以通过 /graphql
路由(例如 localhost:1337/graphql )访问 GraphQL Sandbox。
¥Once the plugin is installed, the GraphQL Sandbox is accessible at the /graphql
route (e.g., localhost:1337/graphql ) when your Strapi application server is running.
配置
¥Configuration
文档插件的大多数配置选项都通过你的 Strapi 项目的代码处理,尽管 GraphQL 在线运行也提供了一些非特定的 Strapi 设置。
¥Most configuration options for the Documentation plugin are handled via your Strapi project's code, though the GraphQL playground also offers some non-specific Strapi settings.
管理面板设置
¥Admin panel settings
Strapi 管理面板不提供 GraphQL 插件的 Strapi 特定设置。但是,在 /graphql
路由上可访问的 GraphQL Playground 是一个嵌入式 Apollo Server 在线运行,因此它包括此类实例可用的所有配置和设置。有关详细信息,请参阅官方 GraphQL 在线运行文档 。
¥The Strapi admin panel does not provide Strapi-specific settings for the GraphQL plugin. However, the GraphQL Playground accessible at the /graphql
route is an embedded Apollo Server playground, so it includes all configuration and settings available with such an instance. Please refer to the official GraphQL playground documentation for details.
基于代码的配置
¥Code-based configuration
插件配置在 config/plugins.js
文件 中定义。此配置文件可以包含一个 graphql.config
对象来定义 GraphQL 插件的特定配置。
¥Plugins configuration are defined in the config/plugins.js
file. This configuration file can include a graphql.config
object to define specific configurations for the GraphQL plugin.
可用选项
¥Available options
Apollo 服务器 选项可以通过 graphql.config.apolloServer
配置对象直接传递给 Apollo。例如,可以使用 Apollo Server 选项来启用 追踪功能 ,它由 GraphQL Sandbox 支持,用于跟踪查询每个部分的响应时间。Apollo Server
默认缓存选项是 cache: 'bounded'
。你可以在 apolloServer
配置中更改它。有关更多信息,请访问Apollo 服务器文档 。
¥Apollo Server options can be passed directly to Apollo with the graphql.config.apolloServer
configuration object. Apollo Server options can be used for instance to enable the tracing feature , which is supported by the GraphQL Sandbox to track the response time of each part of your query. The Apollo Server
default cache option is cache: 'bounded'
. You can change it in the apolloServer
configuration. For more information visit Apollo Server Docs .
GraphQL 插件具有以下特定配置选项,应在 config/plugins
文件中的 graphql.config
对象中声明。所有参数都是可选的:
¥The GraphQL plugin has the following specific configuration options that should be declared in a graphql.config
object within the config/plugins
file. All parameters are optional:
选项 | 类型 | 描述 | 默认值 | 注意 |
---|---|---|---|---|
endpoint | 字符串 | 设置 GraphQL 端点路径。 | '/graphql' | 示例:/custom-graphql |
shadowCRUD | 布尔值 | 启用或禁用内容类型的自动架构生成。 | true | |
depthLimit | 数字 | 限制 GraphQL 查询的深度以防止过度嵌套。 | 10 | 使用它来缓解潜在的 DoS 攻击。 |
amountLimit | 数字 | 限制单个响应中返回的最大项目数。 | 100 | 请谨慎使用以避免性能问题。 |
playgroundAlways | 布尔值 | [已弃用] 在所有环境中启用 GraphQL Playground(已弃用)。 | false | 最好使用 landingPage 。 |
landingPage | 布尔值 | 函数 | 启用或禁用 GraphQL 的登录页面。接受布尔值或返回布尔值的函数或实现 renderLandingPage 的 ApolloServerPlugin。 | 生产环境中为 false ,其他环境中为 true | |
apolloServer | 目的 | 将配置选项直接传递给 Apollo Server。 | {} | 示例:{ tracing: true } |
默认情况下,响应返回的最大项目数限制为 100。可以使用 amountLimit
配置选项更改此值,但只有在仔细考虑后才应更改:大型查询可能会导致 DDoS(分布式拒绝服务),并可能导致 Strapi 服务器以及数据库服务器负载异常。
¥The maximum number of items returned by the response is limited to 100 by default. This value can be changed using the amountLimit
configuration option, but should only be changed after careful consideration: a large query can cause a DDoS (Distributed Denial of Service) and may cause abnormal load on your Strapi server, as well as your database server.
GraphQL Sandbox 在除生产环境以外的所有环境中默认启用。将 landingPage
配置选项设置为 true
,以便在生产环境中启用 GraphQL 沙盒。
¥The GraphQL Sandbox is enabled by default in all environments except production. Set the landingPage
configuration option to true
to also enable the GraphQL Sandbox in production environments.
以下是自定义配置示例:
¥The following is an example custom configuration:
- JavaScript
- TypeScript
module.exports = {
graphql: {
config: {
endpoint: '/graphql',
shadowCRUD: true,
landingPage: false, // disable Sandbox everywhere
depthLimit: 7,
amountLimit: 100,
apolloServer: {
tracing: false,
},
},
},
};
export default () => ({
graphql: {
config: {
endpoint: '/graphql',
shadowCRUD: true,
landingPage: false, // disable Sandbox everywhere
depthLimit: 7,
amountLimit: 100,
apolloServer: {
tracing: false,
},
},
},
})
动态启用 Apollo Sandbox
¥Dynamically enable Apollo Sandbox
你可以使用一个函数根据环境动态启用 Apollo Sandbox:
¥You can use a function to dynamically enable Apollo Sandbox depending on the environment:
- JavaScript
- TypeScript
module.exports = ({ env }) => {
graphql: {
config: {
endpoint: '/graphql',
shadowCRUD: true,
landingPage: (strapi) => {
if (env("NODE_ENV") !== "production") {
return true;
} else {
return false;
}
},
},
},
};
export default ({ env }) => {
graphql: {
config: {
endpoint: '/graphql',
shadowCRUD: true,
landingPage: (strapi) => {
if (env("NODE_ENV") !== "production") {
return true;
} else {
return false;
}
},
},
},
};
着陆页的 CORS 例外
¥CORS exceptions for Landing Page
如果在生产环境中启用了登录页面(不推荐),则必须手动添加 Apollo Server 登录页面的 CORS 标头。
¥If the landing page is enabled in production environments (which is not recommended), CORS headers for the Apollo Server landing page must be added manually.
要全局添加它们,你可以将以下内容合并到中间件配置中:
¥To add them globally, you can merge the following into your middleware configuration:
{
name: "strapi::security",
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
"connect-src": ["'self'", "https:", "apollo-server-landing-page.cdn.apollographql.com"],
"img-src": ["'self'", "data:", "blob:", "apollo-server-landing-page.cdn.apollographql.com"],
"script-src": ["'self'", "'unsafe-inline'", "apollo-server-landing-page.cdn.apollographql.com"],
"style-src": ["'self'", "'unsafe-inline'", "apollo-server-landing-page.cdn.apollographql.com"],
"frame-src": ["sandbox.embed.apollographql.com"]
}
}
}
}
要仅为 /graphql
路径添加这些例外(推荐),你可以创建一个新的中间件来处理它。例如:
¥To add these exceptions only for the /graphql
path (recommended), you can create a new middleware to handle it. For example:
- JavaScript
- TypeScript
module.exports = (config, { strapi }) => {
return async (ctx, next) => {
if (ctx.request.path === '/graphql') {
ctx.set('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net apollo-server-landing-page.cdn.apollographql.com; connect-src 'self' https:; img-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; media-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; frame-src sandbox.embed.apollographql.com; manifest-src apollo-server-landing-page.cdn.apollographql.com;");
}
await next();
};
};
export default (config, { strapi }) => {
return async (ctx, next) => {
if (ctx.request.path === '/graphql') {
ctx.set('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net apollo-server-landing-page.cdn.apollographql.com; connect-src 'self' https:; img-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; media-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; frame-src sandbox.embed.apollographql.com; manifest-src apollo-server-landing-page.cdn.apollographql.com;");
}
await next();
};
};
影子增删改查
¥Shadow CRUD
为了简化和自动化 GraphQL 模式的构建,我们引入了 Shadow CRUD 功能。它根据你的模型自动生成类型定义、查询、突变和解析器。
¥To simplify and automate the build of the GraphQL schema, we introduced the Shadow CRUD feature. It automatically generates the type definitions, queries, mutations and resolvers based on your models.
示例:
¥Example:
如果你使用 交互式 strapi generate
CLI 或管理面板生成了名为 Document
的 API,则你的模型如下所示:
¥If you've generated an API called Document
using the interactive strapi generate
CLI or the administration panel, your model looks like this:
{
"kind": "collectionType",
"collectionName": "documents",
"info": {
"singularName": "document",
"pluralName": "documents",
"displayName": "document",
"name": "document"
},
"options": {
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"name": {
"type": "string"
},
"description": {
"type": "richtext"
},
"locked": {
"type": "boolean"
}
}
}
Generated GraphQL type and queries
# Document's Type definition
input DocumentFiltersInput {
name: StringFilterInput
description: StringFilterInput
locked: BooleanFilterInput
createdAt: DateTimeFilterInput
updatedAt: DateTimeFilterInput
publishedAt: DateTimeFilterInput
and: [DocumentFiltersInput]
or: [DocumentFiltersInput]
not: DocumentFiltersInput
}
input DocumentInput {
name: String
description: String
locked: Boolean
createdAt: DateTime
updatedAt: DateTime
publishedAt: DateTime
}
type Document {
name: String
description: String
locked: Boolean
createdAt: DateTime
updatedAt: DateTime
publishedAt: DateTime
}
type DocumentEntity {
id: ID
attributes: Document
}
type DocumentEntityResponse {
data: DocumentEntity
}
type DocumentEntityResponseCollection {
data: [DocumentEntity!]!
meta: ResponseCollectionMeta!
}
type DocumentRelationResponseCollection {
data: [DocumentEntity!]!
}
# Queries to retrieve one or multiple restaurants.
type Query {
document(id: ID): DocumentEntityResponse
documents(
filters: DocumentFiltersInput
pagination: PaginationArg = {}
sort: [String] = []
publicationState: PublicationState = LIVE
):DocumentEntityResponseCollection
}
# Mutations to create, update or delete a restaurant.
type Mutation {
createDocument(data: DocumentInput!): DocumentEntityResponse
updateDocument(id: ID!, data: DocumentInput!): DocumentEntityResponse
deleteDocument(id: ID!): DocumentEntityResponse
}
定制化
¥Customization
Strapi 提供了一个编程 API 来自定义 GraphQL,它允许:
¥Strapi provides a programmatic API to customize GraphQL, which allows:
-
禁用 影子增删改查 的某些操作
¥disabling some operations for the Shadow CRUD
-
使用获取器 返回有关允许操作的信息
¥using getters to return information about allowed operations
-
向 扩展现有架构 注册并使用
extension
对象(例如扩展类型或定义自定义解析器、策略和中间件)¥registering and using an
extension
object to extend the existing schema (e.g. extend types or define custom resolvers, policies and middlewares)
Example of GraphQL customizations
- JavaScript
- TypeScript
module.exports = {
/**
* An asynchronous register function that runs before
* your application is initialized.
* * This gives you an opportunity to extend code.
*/
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.shadowCRUD('api::restaurant.restaurant').disable();
extensionService.shadowCRUD('api::category.category').disableQueries();
extensionService.shadowCRUD('api::address.address').disableMutations();
extensionService.shadowCRUD('api::document.document').field('locked').disable();
extensionService.shadowCRUD('api::like.like').disableActions(['create', 'update', 'delete']);
const extension = ({ nexus }) => ({
// Nexus
types: [
nexus.objectType({
name: 'Book',
definition(t) {
t.string('title');
},
}),
],
plugins: [
nexus.plugin({
name: 'MyPlugin',
onAfterBuild(schema) {
console.log(schema);
},
}),
],
// GraphQL SDL
typeDefs: `
type Article {
name: String
}
`,
resolvers: {
Query: {
address: {
resolve() {
return { value: { city: 'Montpellier' } };
},
},
},
},
resolversConfig: {
'Query.address': {
auth: false,
},
},
});
extensionService.use(extension);
},
};
export default {
/**
* An asynchronous register function that runs before
* your application is initialized.
* * This gives you an opportunity to extend code.
*/
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.shadowCRUD('api::restaurant.restaurant').disable();
extensionService.shadowCRUD('api::category.category').disableQueries();
extensionService.shadowCRUD('api::address.address').disableMutations();
extensionService.shadowCRUD('api::document.document').field('locked').disable();
extensionService.shadowCRUD('api::like.like').disableActions(['create', 'update', 'delete']);
const extension = ({ nexus }) => ({
// Nexus
types: [
nexus.objectType({
name: 'Book',
definition(t) {
t.string('title');
},
}),
],
plugins: [
nexus.plugin({
name: 'MyPlugin',
onAfterBuild(schema) {
console.log(schema);
},
}),
],
// GraphQL SDL
typeDefs: `
type Article {
name: String
}
`,
resolvers: {
Query: {
address: {
resolve() {
return { value: { city: 'Montpellier' } };
},
},
},
},
resolversConfig: {
'Query.address': {
auth: false,
},
},
});
extensionService.use(extension);
},
};
禁用 Shadow CRUD 中的操作
¥Disabling operations in the Shadow CRUD
GraphQL 插件提供的 extension
服务公开了可用于禁用 Content-Types 操作的函数:
¥The extension
service provided with the GraphQL plugin exposes functions that can be used to disable operations on Content-Types:
内容类型功能 | 描述 | 参数类型 | 可能的参数值 |
---|---|---|---|
disable() | 完全禁用内容类型 | * | * |
disableQueries() | 仅禁用 Content-Type 的查询 | * | * |
disableMutations() | 仅禁用 Content-Type 的突变 | * | * |
disableAction() | 禁用 Content-Type 的特定操作 | 字符串 | 列表中的一个值:
|
disableActions() | 禁用 Content-Type 的特定操作 | 字符串数组 | 列表中的多个值:
|
还可以在字段级别禁用操作,具有以下功能:
¥Actions can also be disabled at the field level, with the following functions:
字段函数 | 描述 |
---|---|
disable() | 完全禁用该字段 |
disableOutput() | 禁用字段上的输出 |
disableInput() | 禁用字段上的输入 |
disableFilters() | 禁用字段上的过滤器输入 |
示例:
¥Examples:
// Disable the 'find' operation on the 'restaurant' content-type in the 'restaurant' API
strapi
.plugin('graphql')
.service('extension')
.shadowCRUD('api::restaurant.restaurant')
.disableAction('find')
// Disable the 'name' field on the 'document' content-type in the 'document' API
strapi
.plugin('graphql')
.service('extension')
.shadowCRUD('api::document.document')
.field('name')
.disable()
使用获取器
¥Using getters
以下 getter 可用于检索有关内容类型上允许的操作的信息:
¥The following getters can be used to retrieve information about operations allowed on content-types:
内容类型 getter | 描述 | 参数类型 | 可能的参数值 |
---|---|---|---|
isEnabled() | 返回是否启用内容类型 | * | * |
isDisabled() | 返回内容类型是否被禁用 | * | * |
areQueriesEnabled() | 返回是否在内容类型上启用查询 | * | * |
areQueriesDisabled() | 返回是否在内容类型上禁用查询 | * | * |
areMutationsEnabled() | 返回是否在内容类型上启用突变 | * | * |
areMutationsDisabled() | 返回是否在内容类型上禁用突变 | * | * |
isActionEnabled(action) | 返回传递的 action 是否在内容类型上启用 | 字符串 | 列表中的一个值:
|
isActionDisabled(action) | 返回传递的 action 是否在内容类型上禁用 | 字符串 | 列表中的一个值:
|
以下 getter 可用于检索有关字段上允许的操作的信息:
¥The following getters can be used to retrieve information about operations allowed on fields:
字段获取器 | 描述 |
---|---|
isEnabled() | 返回字段是否启用 |
isDisabled() | 返回字段是否被禁用 |
hasInputEnabled() | 返回字段是否启用输入 |
hasOutputEnabled() | 返回字段是否启用输出 |
hasFiltersEnabled() | 返回字段是否启用过滤 |
扩展架构
¥Extending the schema
可以通过注册扩展来扩展 Content API 生成的架构。
¥The schema generated by the Content API can be extended by registering an extension.
此扩展定义为对象或返回对象的函数,将由 GraphQL 插件提供的 extension
service 公开的 use()
函数使用。
¥This extension, defined either as an object or a function returning an object, will be used by the use()
function exposed by the extension
service provided with the GraphQL plugin.
描述扩展的对象接受以下参数:
¥The object describing the extension accepts the following parameters:
范围 | 类型 | 描述 |
---|---|---|
types | 数组 | 允许使用基于 关系 的类型定义扩展架构类型 |
typeDefs | 字符串 | 允许使用基于 GraphQL SDL 的类型定义扩展架构类型 |
plugins | 数组 | 允许使用 Nexus plugins 扩展架构 |
resolvers | 目的 | 定义自定义解析器 |
resolversConfig | 目的 | 定义 解析器的配置选项,例如 authorization、policies 和 middlewares |
types
和 plugins
参数基于 关系 。要使用它们,请将扩展注册为以 nexus
作为参数的函数:
¥The types
and plugins
parameters are based on Nexus . To use them, register the extension as a function that takes nexus
as a parameter:
Example:
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
const extension = ({ nexus }) => ({
types: [
nexus.objectType({
…
}),
],
plugins: [
nexus.plugin({
…
})
]
})
strapi.plugin('graphql').service('extension').use(extension)
}
}
export default {
register({ strapi }) {
const extension = ({ nexus }) => ({
types: [
nexus.objectType({
…
}),
],
plugins: [
nexus.plugin({
…
})
]
})
strapi.plugin('graphql').service('extension').use(extension)
}
}
解析器的自定义配置
¥Custom configuration for resolvers
解析器是 GraphQL 查询或突变处理程序(即为 GraphQL 查询或突变生成响应的函数或函数集合)。每个字段都有一个默认解析器。
¥A resolver is a GraphQL query or mutation handler (i.e. a function, or a collection of functions, that generate(s) a response for a GraphQL query or mutation). Each field has a default resolver.
当 扩展 GraphQL 架构 时,resolversConfig
键可用于定义解析器的自定义配置,其中可以包括:
¥When extending the GraphQL schema, the resolversConfig
key can be used to define a custom configuration for a resolver, which can include:
-
授权配置 与
auth
键¥authorization configuration with the
auth
key -
¥and middlewares with the
middlewares
key
授权配置
¥Authorization configuration
默认情况下,GraphQL 请求的授权由注册的授权策略处理,可以是 API 令牌 或通过 用户和权限插件。用户和权限插件提供了更精细的控制。
¥By default, the authorization of a GraphQL request is handled by the registered authorization strategy that can be either API token or through the Users & Permissions plugin. The Users & Permissions plugin offers a more granular control.
Authorization with the Users & Permissions plugin
使用用户和权限插件,如果授予适当的权限,则允许 GraphQL 请求。
¥With the Users & Permissions plugin, a GraphQL request is allowed if the appropriate permissions are given.
例如,如果 '类别' 内容类型存在,并且通过 GraphQL 使用 Query.categories
处理程序进行查询,则如果为 '类别' 内容类型提供了适当的 find
权限,则允许该请求。
¥For instance, if a 'Category' content-type exists and is queried through GraphQL with the Query.categories
handler, the request is allowed if the appropriate find
permission for the 'Categories' content-type is given.
要查询单个类别(使用 Query.category
处理程序完成),如果给出 findOne
权限,则允许该请求。
¥To query a single category, which is done with the Query.category
handler, the request is allowed if the the findOne
permission is given.
请参阅用户指南了解如何 使用用户和权限插件定义权限。
¥Please refer to the user guide on how to define permissions with the Users & Permissions plugin.
要更改授权的配置方式,请使用 resolversConfig.[MyResolverName]
处定义的解析器配置。授权可以配置:
¥To change how the authorization is configured, use the resolver configuration defined at resolversConfig.[MyResolverName]
. The authorization can be configured:
-
要么使用
auth: false
完全绕过授权系统并允许所有请求,¥either with
auth: false
to fully bypass the authorization system and allow all requests, -
或者使用接受字符串数组的
scope
属性来定义授权请求所需的权限。¥or with a
scope
attribute that accepts an array of strings to define the permissions required to authorize the request.
Examples of authorization configuration
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
/**
* Querying the Categories content-type
* bypasses the authorization system.
*/
auth: false
},
'Query.restaurants': {
/**
* Querying the Restaurants content-type
* requires the find permission
* on the 'Address' content-type
* of the 'Address' API
*/
auth: {
scope: ['api::address.address.find']
}
},
}
})
}
}
export default {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
/**
* Querying the Categories content-type
* bypasses the authorization system.
*/
auth: false
},
'Query.restaurants': {
/**
* Querying the Restaurants content-type
* requires the find permission
* on the 'Address' content-type
* of the 'Address' API
*/
auth: {
scope: ['api::address.address.find']
}
},
}
})
}
}
政策
¥Policies
政策 可以通过 resolversConfig.[MyResolverName].policies
键应用于 GraphQL 解析器。
¥Policies can be applied to a GraphQL resolver through the resolversConfig.[MyResolverName].policies
key.
policies
键是一个接受策略列表的数组,该列表中的每一项要么是对已注册策略的引用,要么是直接传递的实现(请参阅 策略配置文档)。
¥The policies
key is an array accepting a list of policies, each item in this list being either a reference to an already registered policy or an implementation that is passed directly (see policies configuration documentation).
resolversConfig
中直接实现的策略是以 context
对象和 strapi
实例作为参数的函数。context
对象可以访问:
¥Policies directly implemented in resolversConfig
are functions that take a context
object and the strapi
instance as arguments.
The context
object gives access to:
-
GraphQL 解析器的
parent
、args
、context
和info
参数,¥the
parent
,args
,context
andinfo
arguments of the GraphQL resolver, -
Koa 的 context 带有
context.http
和 state 带有context.state
。¥Koa's context with
context.http
and state withcontext.state
.
Example of GraphQL policies applied to resolvers
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
policies: [
(context, { strapi }) => {
console.log('hello', context.parent)
/**
* If 'categories' have a parent, the function returns true,
* so the request won't be blocked by the policy.
*/
return context.parent !== undefined;
}
/**
* Uses a policy already created in Strapi.
*/
"api::model.policy-name",
/**
* Uses a policy already created in Strapi with a custom configuration
*/
{name:"api::model.policy-name", config: {/* all config values I want to pass to the strapi policy */} },
],
auth: false,
},
}
})
}
}
export default {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
policies: [
(context, { strapi }) => {
console.log('hello', context.parent)
/**
* If 'categories' have a parent, the function returns true,
* so the request won't be blocked by the policy.
*/
return context.parent !== undefined;
}
/**
* Uses a policy already created in Strapi.
*/
"api::model.policy-name",
/**
* Uses a policy already created in Strapi with a custom configuration
*/
{name:"api::model.policy-name", config: {/* all the configuration values to pass to the strapi policy */} },
],
auth: false,
},
}
})
}
}
中间件
¥Middlewares
中间件 可以通过 resolversConfig.[MyResolverName].middlewares
键应用于 GraphQL 解析器。GraphQL 和 REST 实现之间的唯一区别是 config
键变为 options
。
¥Middlewares can be applied to a GraphQL resolver through the resolversConfig.[MyResolverName].middlewares
key. The only difference between the GraphQL and REST implementations is that the config
key becomes options
.
middlewares
键是一个接受中间件列表的数组,该列表中的每个项目要么是对已注册中间件的引用,要么是直接传递的实现(请参阅 中间件配置文档)。
¥The middlewares
key is an array accepting a list of middlewares, each item in this list being either a reference to an already registered middleware or an implementation that is passed directly (see middlewares configuration documentation).
直接在 resolversConfig
中实现的中间件可以将 GraphQL 解析器的 `parent`、`args`、`context` 和 `info` 对象 作为参数。
¥Middlewares directly implemented in resolversConfig
can take the GraphQL resolver's `parent`, `args`, `context` and `info` objects as arguments.
使用 GraphQL 的中间件甚至可以作用于嵌套解析器,这提供了比 REST 更精细的控制。
¥Middlewares with GraphQL can even act on nested resolvers, which offer a more granular control than with REST.
Examples of GraphQL middlewares applied to a resolver
- JavaScript
- TypeScript
module.exports = {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
middlewares: [
/**
* Basic middleware example #1
* Log resolving time in console
*/
async (next, parent, args, context, info) => {
console.time('Resolving categories');
// call the next resolver
const res = await next(parent, args, context, info);
console.timeEnd('Resolving categories');
return res;
},
/**
* Basic middleware example #2
* Enable server-side shared caching
*/
async (next, parent, args, context, info) => {
info.cacheControl.setCacheHint({ maxAge: 60, scope: "PUBLIC" });
return next(parent, args, context, info);
},
/**
* Basic middleware example #3
* change the 'name' attribute of parent with id 1 to 'foobar'
*/
(resolve, parent, ...rest) => {
if (parent.id === 1) {
return resolve({...parent, name: 'foobar' }, ...rest);
}
return resolve(parent, ...rest);
}
/**
* Basic middleware example #4
* Uses a middleware already created in Strapi.
*/
"api::model.middleware-name",
/**
* Basic middleware example #5
* Uses a middleware already created in Strapi with a custom configuration
*/
{ name: "api::model.middleware-name", options: { /* all config values I want to pass to the strapi middleware */ } },
],
auth: false,
},
}
})
}
}
export default {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension');
extensionService.use({
resolversConfig: {
'Query.categories': {
middlewares: [
/**
* Basic middleware example #1
* Log resolving time in console
*/
async (next, parent, args, context, info) => {
console.time('Resolving categories');
// call the next resolver
const res = await next(parent, args, context, info);
console.timeEnd('Resolving categories');
return res;
},
/**
* Basic middleware example #2
* Enable server-side shared caching
*/
async (next, parent, args, context, info) => {
info.cacheControl.setCacheHint({ maxAge: 60, scope: "PUBLIC" });
return next(parent, args, context, info);
},
/**
* Basic middleware example #3
* change the 'name' attribute of parent with id 1 to 'foobar'
*/
(resolve, parent, ...rest) => {
if (parent.id === 1) {
return resolve({...parent, name: 'foobar' }, ...rest);
}
return resolve(parent, ...rest);
}
/**
* Basic middleware example #4
* Uses a middleware already created in Strapi.
*/
"api::model.middleware-name",
/**
* Basic middleware example #5
* Uses a middleware already created in Strapi with a custom configuration
*/
{name:"api::model.middleware-name", options: {/* all the configuration values to pass to the middleware */} },
],
auth: false,
},
}
})
}
}
安全
¥Security
GraphQL 是一种查询语言,允许用户使用比传统 REST API 更广泛的输入面板。GraphQL API 本质上容易出现安全风险,例如凭证泄露和拒绝服务攻击,可以通过采取适当的预防措施来减少这些风险。
¥GraphQL is a query language allowing users to use a broader panel of inputs than traditional REST APIs. GraphQL APIs are inherently prone to security risks, such as credential leakage and denial of service attacks, that can be reduced by taking appropriate precautions.