默认情况下,Strapi 会为您的每种内容类型创建 REST 端点。使用 GraphQL 插件,您将能够添加 GraphQL 端点来获取和改变您的内容。
GraphQL API 参考 描述了您可以使用 Strapi 的 GraphQL 插件与您的 API 交互的查询、改变和参数。
用法
要在您的应用程序中开始使用 GraphQL,请先安装插件。为此,请打开您的终端并运行以下命令:
yarn strapi install graphql
然后,启动您的应用并在 http://localhost:1337/graphql 打开浏览器。您现在应该能够访问 GraphQL Playground,它将帮助您编写 GraphQL 查询和突变。
配置
插件配置在 config/plugins.js|ts
文件中定义。此配置文件可以包含一个 graphql.config
对象来定义 GraphQL 插件的特定配置(请参阅 插件配置文档)。
Apollo Server 选项可以使用 graphql.config.apolloServer
配置对象 设置。例如,可以使用 Apollo Server 选项来启用 跟踪功能,该功能由 GraphQL 游乐场支持,用于跟踪查询每个部分的响应时间。从 Apollo Server
版本 3.9 开始,默认缓存选项为 cache: 'bounded'
。您可以在 apolloServer
配置中更改它。有关更多信息,请访问 Apollo Server 文档。
默认情况下,响应返回的最大项目数限制为 100。可以使用 defaultLimit
配置选项更改此值,但应在仔细考虑后再更改:大型查询可能会导致 DDoS(分布式拒绝服务),并可能导致 Strapi 服务器以及数据库服务器负载异常。
module.exports = {
//
graphql: {
config: {
endpoint: '/graphql',
shadowCRUD: true,
playgroundAlways: false,
depthLimit: 7,
amountLimit: 100,
apolloServer: {
tracing: false,
},
},
},
}
Shadow CRUD
为了简化和自动化 GraphQL 模式的构建,我们引入了 Shadow CRUD 功能。它会根据您的模型自动生成类型定义、查询、变异和解析器。
示例:
如果您使用 交互式 strapi generate
CLI 或管理面板生成了名为 Document
的 API,则您的模型如下所示:
{
"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"
}
}
}
生成的 GraphQL 类型和查询
自定义
Strapi 提供了一个编程 API 来自定义 GraphQL,它允许:
- 禁用 Shadow CRUD 的某些操作
- 使用 getters 返回有关允许操作的信息
- 注册并使用
extension
对象来 扩展现有架构(例如扩展类型或定义自定义解析器、策略和中间件)
GraphQL 自定义示例
禁用 Shadow CRUD 中的操作
GraphQL 插件提供的 extension
服务 公开了可用于禁用 Content-Type 操作的函数:
Content-type 函数 | 说明 | 参数类型 | 可能的参数值 |
---|---|---|---|
disable() | 完全禁用 Content-Type | - | - |
disableQueries() | 仅禁用 Content-Type 的查询 | - | - |
disableMutations() | 仅禁用 Content-Type 的突变 | - | - |
disableAction() | 禁用 Content-Type 的特定操作 | 字符串 | 列表中的一个值:
|
disableActions() | 禁用 Content-Type 的特定操作 | 字符串数组 | 列表中的多个值:
|
还可以在字段级别禁用操作,使用以下函数:
字段函数 | 说明 |
---|---|
disable() | 完全禁用字段 |
disableOutput() | 禁用字段上的输出 |
disableInput() | 禁用字段上的输入 |
disableFilters() | 禁用字段上的过滤器输入 |
例子:
// 禁用“restaurant”API 中“restaurant”内容类型的“find”操作
strapi
.plugin('graphql')
.service('extension')
.shadowCRUD('api::restaurant.restaurant')
.disableAction('find')
// 禁用“document”API 中“document”内容类型的“name”字段
strapi
.plugin('graphql')
.service('extension')
.shadowCRUD('api::document.document')
.field('name')
.disable()
使用 getter
以下 getter 可用于检索有关内容类型上允许的操作的信息:
内容类型 getter | 说明 | 参数类型 | 可能的参数值 |
---|---|---|---|
isEnabled() | 返回内容类型是否已启用 | - | - |
isDisabled() | 返回内容类型是否已禁用 | - | - |
areQueriesEnabled() | 返回内容类型上是否启用查询 | - | - |
areQueriesDisabled() | 返回内容类型上是否禁用查询 | - | - |
areMutationsEnabled() | 返回内容类型上是否启用突变 | - | - |
areMutationsDisabled() | 返回内容类型上是否禁用突变 | - | - |
isActionEnabled(action) | 返回所传递的 action 是否在内容类型上启用 | 字符串 | 列表中的一个值:
|
isActionDisabled(action) | 返回所传递的 action 是否在内容类型上禁用 | 字符串 | 列表中的一个值:
|
以下 getter 可用于检索有关字段上允许的操作的信息:
字段 getter | 说明 |
---|---|
isEnabled() | 返回字段是否已启用 |
isDisabled() | 返回字段是否被禁用 |
hasInputEnabled() | 返回字段是否启用了输入 |
hasOutputEnabled() | 返回字段是否启用了输出 |
hasFiltersEnabled() | 返回字段是否启用了过滤 |
扩展架构
可以通过注册扩展来扩展 Content API 生成的架构。
此扩展定义为对象或返回对象的函数,将由 GraphQL 插件提供的 extension
服务 公开的 use()
函数使用。
描述扩展的对象接受以下参数:
参数 | 类型 | 描述 |
---|---|---|
types | Array | 允许使用基于 Nexus 的类型定义扩展架构类型 |
typeDefs | String | 允许使用 GraphQL SDL 扩展架构类型 |
plugins | Array | 允许使用 Nexus 插件 扩展架构 |
resolvers | 对象 | 定义自定义解析器 |
resolversConfig | 对象 | 定义 解析器的配置选项,例如 authorization、policies 和 middlewares |
types
和 plugins
参数基于 Nexus。要使用它们,请将扩展注册为以 nexus
作为参数的函数:
module.exports = {
register({ strapi }) {
const extension = ({ nexus }) => ({
types: [
nexus.objectType({
// ...
}),
],
plugins: [
nexus.plugin({
// ...
})
]
})
strapi.plugin('graphql').service('extension').use(extension)
}
}
解析器的自定义配置
解析器是 GraphQL 查询或突变处理程序(即为 GraphQL 查询或突变生成响应的函数或函数集合)。每个字段都有一个默认解析器。
当 扩展 GraphQL 架构 时,resolversConfig
键可用于定义解析器的自定义配置,其中可以包括:
- 带有
auth
键的 授权配置 - 带有
policies
键的策略 - 和 带有
middlewares
键的中间件
授权配置
默认情况下,GraphQL 请求的授权由已注册的授权策略处理,该策略可以是 API 令牌 或通过 用户和权限插件。用户和权限插件提供更精细的控制。
使用用户和权限插件进行授权
要更改授权配置方式,请使用在 resolversConfig.[MyResolverName]
中定义的解析器配置。可以配置授权:
- 使用
auth: false
完全绕过授权系统并允许所有请求, - 或使用
scope
属性,该属性接受字符串数组来定义授权请求所需的权限。
授权配置示例
策略
策略 可通过 resolversConfig.[MyResolverName].policies
键应用于 GraphQL 解析器。
policies
键是一个接受策略列表的数组,此列表中的每个项目要么是对已注册策略的引用,要么是直接传递的实现(请参阅 策略配置文档)。
直接在 resolversConfig
中实现的策略是将 context
对象和 strapi
实例作为参数的函数。
context
对象允许访问:
应用于解析器的 GraphQL 策略示例
Middlewares
中间件 可通过 resolversConfig.[MyResolverName].middlewares
键应用于 GraphQL 解析器。GraphQL 和 REST 实现之间的唯一区别是 config
键变为 options
。
middlewares
键是一个接受中间件列表的数组,此列表中的每个项目要么是对已注册中间件的引用,要么是直接传递的实现(请参阅 中间件配置文档)。
直接在 resolversConfig
中实现的中间件可以将 GraphQL 解析器的 parent
、args
、context
和 info
对象 作为参数。
带有 GraphQL 的中间件甚至可以作用于嵌套解析器,这比 REST 提供了更精细的控制。
应用于解析器的 GraphQL 中间件示例
与用户和权限插件一起使用
用户和权限插件 是一个可选插件,允许使用完整的身份验证过程保护 API。
注册
通常,您需要先注册或登记,然后才能被识别为用户,然后执行授权请求。
mutation {
register(input: { username: "username", email: "email", password: "password" }) {
jwt
user {
username
email
}
}
}
您应该会看到在 Strapi 管理面板中的“用户”集合类型中创建了一个新用户。
身份验证
要执行授权请求,您必须首先获取 JWT:
mutation {
login(input: { identifier: "email", password: "password" }) {
jwt
}
}
然后在每个请求中,以 { "Authorization": "Bearer YOUR_JWT_GOES_HERE" }
的形式发送 Authorization
标头。这可以在 GraphQL Playground 的 HTTP Headers 部分中设置。
API 令牌
要使用 API 令牌进行身份验证,请使用 Bearer your-api-token
格式在 Authorization
标头中传递令牌。
在 GraphQL Playground 中使用 API 令牌需要在 HTTP HEADERS
选项卡中添加带有令牌的授权标头:
{
"Authorization" : "Bearer <TOKEN>"
}
将 <TOKEN>
替换为在 Strapi 管理面板中生成的 API 令牌。
安全性
GraphQL 是一种查询语言,允许用户使用比传统 REST API 更广泛的输入面板。 GraphQL API 本质上容易受到安全风险的影响,例如凭据泄露和拒绝服务攻击,可以通过采取适当的预防措施来减少这些风险。
在生产环境中禁用 Playground
在生产环境中,建议禁用 GraphQL Playground。
如果您尚未编辑 配置文件,则默认情况下它在生产中已禁用。
限制最大深度和复杂性
恶意用户可能会发送深度非常大的查询,这可能会使您的服务器过载。使用 depthLimit
配置参数 来限制可以在单个请求中查询的最大嵌套字段数。默认情况下,depthLimit
设置为 10,但在测试和开发期间可以设置为更高的值。
为了进一步提高 GraphQL 的安全性,可以使用第三方工具。请参阅论坛上有关 使用 GraphQL Armor 和 Strapi 的指南。