GraphQL API
Tier: 基础版,专业版,旗舰版
Offering: JihuLab.com,私有化部署
GraphQL 是一种用于 API 的查询语言。你可以使用它来请求所需的确切数据,从而限制你所需的请求数量。
GraphQL 数据按类型进行组织,因此你的客户端可以使用客户端 GraphQL 库来消费 API,并避免手动解析。
极狐GitLab GraphQL API 是无版本的。
入门
如果你刚开始使用极狐GitLab GraphQL API,请参阅极狐GitLab GraphQL API 入门指南。
你可以在GraphQL API 参考文档中查看可用资源。
极狐GitLab GraphQL API 的端点位于 /api/graphql。
交互式 GraphQL 浏览器
使用交互式 GraphQL 浏览器探索 GraphQL API,有以下方式:
- 在 JihuLab.com 上。
- 在极狐GitLab 私有化部署实例上的 https://<your-gitlab-site.com>/-/graphql-explorer。
有关更多信息,请参阅 GraphiQL。
查看 GraphQL 示例
你可以使用从 JihuLab.com 上的公共项目拉取数据的示例查询:
入门指南页面包含了自定义 GraphQL 查询的不同方法。
身份验证
访问某些查询无需身份验证,但另一些则需要。变更总是需要身份验证。
你可以使用以下任一方式进行身份验证:
如果身份验证信息无效,极狐GitLab 会返回一条错误消息,状态码为 401:
json{"errors":[{"message":"无效的令牌"}]}
令牌身份验证
使用以下任一令牌对 GraphQL API 进行身份验证:
令牌需要正确的作用域。
标头身份验证
使用 Authorization: Bearer <token> 请求标头进行令牌身份验证的示例:
shellcurl --request POST \ --url "https://jihulab.com/api/graphql" \ --header "Authorization: Bearer <token>" \ --header "Content-Type: application/json" \ --data "{\"query\": \"query {currentUser {name}}\"}"
参数身份验证
在 access_token 参数中使用 OAuth 2.0 令牌的示例:
shellcurl --request POST \ --url "https://jihulab.com/api/graphql?access_token=<oauth_token>" \ --header "Content-Type: application/json" \ --data "{\"query\": \"query {currentUser {name}}\"}"
你可以使用 private_token 参数传入个人、项目或群组访问令牌:
shellcurl --request POST \ --url "https://jihulab.com/api/graphql?private_token=<access_token>" \ --header "Content-Type: application/json" \ --data "{\"query\": \"query {currentUser {name}}\"}"
令牌作用域
令牌必须具有正确的作用域才能访问 GraphQL API,如下所示:
| 作用域 | 访问权限 |
|---|---|
| read_api | 授予对 API 的读取权限。足以进行查询。 |
| api | 授予对 API 的读写权限。变更操作所必需。 |
会话 Cookie 身份验证
登录到极狐GitLab 主应用程序会设置一个 _gitlab_session 会话 Cookie。
交互式 GraphQL 浏览器和极狐GitLab 的 Web 前端本身使用此身份验证方法。
授权
在你进行身份验证后,GraphQL API 会检查你对每个请求资源的权限。API 报告授权失败的方式取决于操作类型。
查询字段
当你没有权限访问某个资源时,查询字段会返回 null。响应中不包含错误消息。
这种行为是故意的。对于未经授权和不存在的资源,API 返回相同的 null 响应,这样客户端就无法枚举服务器上存在哪些资源。
例如,如果你查询一个需要你不具备的角色或附加组件的字段,则 errors 数组中不会显示任何条目:
json1{ 2 "data": { 3 "group": { 4 "fieldRequiringPermission": null 5 } 6 } 7}
对于使用 Relay 分页模式的连接字段,你可以区分授权失败和空结果:
- "field": null 表示你没有权限访问此资源。
- "field": { "nodes": [] } 表示你有权限,但没有与你的查询匹配的数据。
如果你收到意外的 null,请验证:
- 你的令牌具有所需的作用域。
- 你的角色满足 GraphQL API 参考文档中记录的最低访问级别。
- 你的实例启用了所需的订阅级别、功能或附加组件。
变更
当授权失败时,变更会返回一条错误消息。错误出现在顶层 errors 数组中,同时 data 字段为 null:
json1{ 2 "data": { 3 "mutationName": null 4 }, 5 "errors": [ 6 { 7 "message": "你尝试访问的资源不存在或你没有权限执行此操作", 8 "locations": [{ "line": 2, "column": 3 }], 9 "path": ["mutationName"] 10 } 11 ] 12}
错误消息可能因资源类型而异。
对象标识符
极狐GitLab GraphQL API 混合使用多种标识符。
全局 ID、完整路径和内部 ID(IID)都用作极狐GitLab GraphQL API 中的参数,但通常架构的特定部分不会同时接受所有这些标识符。
尽管极狐GitLab GraphQL API 在历史上对此并不一致,但通常你可以预期:
- 如果对象是项目、群组或命名空间,则使用对象的完整路径。
- 如果对象有 IID,则使用完整路径和 IID 的组合。
- 对于其他对象,使用全局 ID。
例如,通过完整路径 "gitlab-cn/gitlab" 查找项目:
graphql1{ 2 project(fullPath: "gitlab-cn/gitlab") { 3 id 4 fullPath 5 } 6}
另一个示例,通过项目的完整路径 "gitlab-cn/gitlab" 和议题的 IID "1" 锁定议题:
graphql1mutation { 2 issueSetLocked(input: { projectPath: "gitlab-cn/gitlab", iid: "1", locked: true }) { 3 issue { 4 id 5 iid 6 } 7 } 8}
通过全局 ID 查找 CI Runner 的示例:
graphql{ runner(id: "gid://gitlab/Ci::Runner/1") { id } }
从历史上看,极狐GitLab GraphQL API 在完整路径和 IID 字段及参数的类型定义上并不一致,但通常:
- 完整路径字段和参数是 GraphQL ID 类型。
- IID 字段和参数是 GraphQL String 类型。
全局 ID
在极狐GitLab GraphQL API 中,名为 id 的字段或参数几乎始终是全局 ID,而绝不是数据库主键 ID。极狐GitLab GraphQL API 中的全局 ID 以 "gid://gitlab/" 开头。例如,"gid://gitlab/Issue/123"。
全局 ID 是一些客户端库用于缓存和获取的约定。
极狐GitLab 全局 ID 可能会发生变化。如果发生更改,旧的全局 ID 作为参数的使用将被弃用,并根据弃用和破坏性变更流程提供支持。你不应期望缓存的全局 ID 在极狐GitLab GraphQL 弃用周期之后仍然有效。
可用的顶层查询
所有查询的顶层入口点均在 GraphQL 参考文档中的 Query 类型中定义。
多路复用查询
极狐GitLab 支持将查询批处理到单个请求中。有关更多信息,请参阅多路复用。
破坏性变更
极狐GitLab GraphQL API 是无版本的,对 API 的更改主要是向后兼容的。
但是,极狐GitLab 有时会以不向后兼容的方式更改 GraphQL API。这些更改被视为破坏性变更,可能包括删除或重命名字段、参数或架构的其他部分。在创建破坏性变更时,极狐GitLab 遵循弃用和移除流程。
为避免破坏性变更影响你的集成,你应该:
对于极狐GitLab 私有化部署,从 EE 实例回退到 CE 会导致破坏性变更。
破坏性变更豁免
在 GraphQL API 参考文档中标记为实验的架构条目不受弃用流程的约束。这些条目可以随时被移除或更改,恕不另行通知。
位于功能标志之后且默认禁用的字段不遵循弃用和移除流程。这些字段可以随时被移除,恕不另行通知。
针对未来的破坏性变更架构进行验证
版本历史
- 在极狐GitLab 15.6 引入,带有一个名为 maven_central_request_forwarding 的功能标志,默认禁用。
- 所需角色从维护者更改为所有者在极狐GitLab 17.0。
你可以像已删除所有已弃用条目一样对 GraphQL API 进行调用。这样,你可以在条目实际从架构中移除之前,在破坏性变更新版本发布之前验证 API 调用。
要进行这些调用,请在 GraphQL API 端点中添加一个 remove_deprecated=true 查询参数。例如,对于 JihuLab.com 上的 GraphQL,使用 https://jihulab.com/api/graphql?remove_deprecated=true。
弃用和移除流程
极狐GitLab GraphQL API 中标记为要移除的架构部分首先会被弃用,但至少在六个版本中仍然可用。然后,在下一个 XX.0 主要版本中完全移除。
条目在以下地方被标记为弃用:
- 架构中。
- GraphQL API 参考文档中。
- 弃用功能移除时间表中,该时间表通过发布帖子链接。
- GraphQL API 的内省查询中。
如果适用,弃用消息会为已弃用的架构条目提供替代方案。
为避免遇到破坏性变更,你应尽快从 GraphQL API 调用中移除已弃用的架构。你应该针对不包含已弃用架构条目的架构验证你的 API 调用。
弃用示例
以下字段在不同的次要版本中被弃用,但都在极狐GitLab 17.0 中被移除:
| 字段弃用于 | 原因 |
|---|---|
| 15.7 | 极狐GitLab 传统上每个主要版本有 12 个次要版本。为确保该字段再可用 6 个版本,它在 17.0 主要版本(而不是 16.0)中被移除。 |
| 16.6 | 在 17.0 中移除允许 6 个月的可用性。 |
已移除条目列表
查看以前版本中已移除的条目列表。
限制
以下限制适用于极狐GitLab GraphQL API。
| 限制 | 默认值 |
|---|---|
| 最大页面大小 | 每页 100 条记录(节点)。适用于 API 中的大多数连接。特定连接可能具有更高或更低的不同最大页面大小限制。 |
| 最大查询复杂度 | 未经身份验证的请求为 200,经身份验证的请求为 250。 |
| 最大查询大小 | 每个查询或变更 10,000 个字符。如果达到此限制,请使用变量和片段来减小查询或变更的大小。最后的手段是移除空白字符。 |
| 速率限制 | 对于 JihuLab.com,请参阅 JihuLab.com 特定的速率限制。 |
| 数据限制 | 当指定多个 blob 路径时,blob 请求限制为 20 MB。 |
| 请求超时 | 30 秒。 |
最大查询复杂度
极狐GitLab GraphQL API 对查询的复杂度进行评分。通常,较大的查询具有较高的复杂度评分。此限制旨在保护 API 免受可能对其整体性能产生负面影响的查询。
你可以查询一个查询的复杂度评分和请求的限制。
如果查询超过复杂度限制,则会返回一条错误消息响应。
通常,查询中的每个字段都会为复杂度评分增加 1,但对于特定字段,这个值可能更高或更低。有时,添加某些参数也可能会增加查询的复杂度。
数据限制
Blob 请求限制为:
- 任意大小的单个 blob。
- 总大小不超过 20 MB 的多个 blob。
大于 20 MB 的 blob 必须单独请求。此限制仅在你请求包含 blob 数据的字段时适用。
你可能需要限制请求中的路径数量,以便保持在数据限制之内。在排除数据字段的同时,请求 size 字段:
gql1{ 2 project(fullPath: "gitlab-cn/gitlab") { 3 repository { 4 blobs(paths: ["big_file.rb", "small_file.rb", "huge_file.rb", ..., etc.], ref: "master") { 5 nodes { 6 path 7 size 8 } 9 } 10 } 11 } 12}
使用响应计算总大小,并确保后续请求不超过 20 MB 的数据限制。
解决被检测为垃圾信息的变更
GraphQL 变更可能被检测为垃圾信息。如果变更被检测为垃圾信息,并且:
-
未配置验证码服务,则会引发 GraphQL 顶层错误。例如:
json1{ 2 "errors": [ 3 { 4 "message": "请求被拒绝。检测到垃圾信息", 5 "locations": [ { "line": 6, "column": 7 } ], 6 "path": [ "updateSnippet" ], 7 "extensions": { 8 "spam": true 9 } 10 } 11 ], 12 "data": { 13 "updateSnippet": { 14 "snippet": null 15 } 16 } 17} -
配置了验证码服务,你会收到一个响应,其中包含:
- needsCaptchaResponse 设置为 true。
- spamLogId 和 captchaSiteKey 字段已设置。
例如:
json1{ 2 "errors": [ 3 { 4 "message": "请求被拒绝。请解决验证码挑战并重试", 5 "locations": [ { "line": 6, "column": 7 } ], 6 "path": [ "updateSnippet" ], 7 "extensions": { 8 "needsCaptchaResponse": true, 9 "captchaSiteKey": "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI", 10 "spamLogId": 67 11 } 12 } 13 ], 14 "data": { 15 "updateSnippet": { 16 "snippet": null, 17 } 18 } 19} -
使用 captchaSiteKey,通过适当的验证码 API 获取验证码响应值。 仅支持 Google reCAPTCHA v2。
-
重新提交带有 X-GitLab-Captcha-Response 和 X-GitLab-Spam-Log-Id 标头的请求。
shell1export CAPTCHA_RESPONSE="<验证码服务获取的验证码响应>" 2export SPAM_LOG_ID="<从初始 REST 响应中获取的 spam_log_id>" 3curl --request POST \ 4 --header "Authorization: Bearer $PRIVATE_TOKEN" \ 5 --header "Content-Type: application/json" \ 6 --header "X-GitLab-Captcha-Response: $CAPTCHA_RESPONSE" \ 7 --header "X-GitLab-Spam-Log-Id: $SPAM_LOG_ID" \ 8 --data-binary '{"query": "mutation {createSnippet(input: {title: \"Title\" visibilityLevel: public blobActions: [ { action: create filePath: \"BlobPath\" content: \"BlobContent\" } ] }) { snippet { id title } errors }}"}' "https://gitlab.example.com/api/graphql"