简介
本文介绍如何通过 GitHub CLI、curl
或 JavaScript 使用 GitHub REST API。 有关快速入门指南,请参阅 GitHub REST API 快速入门。
关于对 REST API 的请求
本节介绍构成 API 请求的元素:
每个对 REST API 的请求都包含一个 HTTP 方法和一个路径。 取决于 REST API 终结点,可能还需要指定请求标头、身份验证信息、查询参数或正文参数。
REST API 参考文档介绍了每个终结点的 HTTP 方法、路径和参数。 它还显示每个终结点的示例请求和响应。 有关详细信息,请查看 REST 参考文档。
HTTP 方法
终结点的 HTTP 方法定义它对给定资源执行的操作类型。 常见的一些 HTTP 方法有 GET
、POST
、DELETE
和 PATCH
。 REST API 参考文档介绍了每个终结点的 HTTP 方法。
例如,“列出存储库问题”终结点的 HTTP 方法为 GET
。
在可能的情况下,GitHub REST API 尽量为每个操作使用适当的 HTTP 方法。
GET
:用于检索资源。POST
:用于创建资源。PATCH
:用于更新资源的属性。PUT
:用于替换资源或集合。DELETE
:用于删除资源。
路径
每个终结点都有一个路径。 REST API 参考文档介绍了每个终结点的路径。 例如,“列出存储库问题”终结点的路径为 /repos/{owner}/{repo}/issues
。
路径中的大括号 {}
表示需要指定的路径参数。 路径参数修改终结点路径,在请求中是必需的。 例如,“列出存储库问题”终结点的路径参数为 {owner}
和 {repo}
。 要在 API 请求中使用此路径,请将 {repo}
替换为想要请求问题列表的存储库的名称,并将 {owner}
替换为存储库所有者帐户的名称。
标头
标头包含有关请求和所需响应的其它信息。 以下是可在对 GitHub REST API 的请求中使用一些标头示例。 有关使用标头的请求示例,请参阅发出请求。
Accept
大多数 GitHub REST API 终结点指定应传递值为 application/vnd.github+json
的 Accept
标头。 Accept
标头的值为媒体类型。 有关媒体类型的详细信息,请参阅媒体类型。
X-GitHub-Api-Version
应使用此标头指定要用于请求的 REST API 版本。 有关详细信息,请参阅“API 版本”。
User-Agent
所有 API 请求都必须包含有效的 User-Agent
标头。 User-Agent
标头标识发出请求的用户或应用程序。
如果使用的是 Octokit.js SDK,则该 SDK 为你发送有效的 User-Agent
标头。 但是,GitHub 建议使用 GitHub 用户名或应用程序名称作为 User-Agent
标头值。 这样,如果存在问题,GitHub 即可与你联系。
下面的示例 User-Agent
是一个名为 Awesome-Octocat-App
的应用:
User-Agent: Awesome-Octocat-App
没有 User-Agent
标头的请求将被拒绝。 如果提供无效的 User-Agent
标头,则将收到 403 Forbidden
响应。
媒体类型
可以通过将媒体类型添加到请求的 Accept
标头来指定一种或多种媒体类型。 有关 Accept
标头的详细信息,请参阅 Accept
。
媒体类型指定要从 API 获取的数据格式。 媒体类型特定于资源,允许它们独立更改并支持其他资源不支持的格式。 每个 GitHub REST API 终结点的文档将描述它支持的媒体类型。 有关详细信息,请参阅 GitHub REST API 文档。
GitHub REST API 支持的最常见媒体类型是 application/vnd.github+json
和 application/json
。
还可以将自定义媒体类型和某些端点搭配使用。 例如,用于管理提交和提取请求的 REST API 支持媒体类型 diff
、patch
和 sha
。 某些其他端点使用媒体类型 full
、raw
、text
或 html
。
GitHub 的全部自定义媒体类型类似于 application/vnd.github.PARAM+json
,其中 PARAM
是媒体类型的名称。 例如,要指定 raw
媒体类型,可以使用 application/vnd.github.raw+json
。
有关使用媒体类型的请求示例,请参阅发出请求。
身份验证
许多终结点需要身份验证或是在进行身份验证后返回其他信息。 此外,进行身份验证后,每小时可以发出更多请求。
要对请求进行身份验证,需要提供具有所需作用域或权限的身份验证令牌。 有几种不同方式获取令牌:可以创建 personal access token,生成包含 GitHub App 的令牌,或使用 GitHub Actions 工作流中内置的 GITHUB_TOKEN
。 有关详细信息,请参阅“对 REST API 进行身份验证”。
有关使用身份验证令牌的请求示例,请参阅发出请求。
Warning
应该像对待密码或其他敏感凭据那样对待访问令牌。 有关详细信息,请参阅“确保 API 凭据安全”。
参数
许多 API 方法要求或允许在请求的参数中发送其他信息。 有几种不同类型的参数:路径参数、正文参数和查询参数。
路径参数
路径参数会修改终结点路径。 这些是请求中的必需参数: 有关详细信息,请参阅 Path。
正文参数
正文参数使你可以将其他数据传递给 API。 上述参数可以是可选参数,也可以是必需参数,具体取决于终结点。 例如,正文参数可能允许在创建新问题时指定问题标题,或在启用/禁用功能时指定某些设置。 每个 GitHub REST API 终结点的文档将描述它支持的正文参数。 有关详细信息,请参阅 GitHub REST API 文档。
例如,“创建问题”终结点要求为请求中的新问题指定标题。 此外,还允许选择指定其他信息,例如要放入问题正文中的文本、要分配给新问题的用户或要应用于新问题的标签。 有关使用正文参数的请求示例,请参阅发出请求。
必须对请求进行身份验证才能传递正文参数。 有关详细信息,请参阅身份验证。
Query parameters
查询参数使你可以控制为请求返回的数据。 这些参数通常是可选的。 每个 GitHub REST API 终结点的文档将描述它支持的任何查询参数。 有关详细信息,请参阅 GitHub REST API 文档。
例如,“列出公共事件”终结点 默认返回 30 个问题。 可以使用 per_page
查询参数返回 2 个问题,而不是 30 个问题。 可以使用 page
查询参数仅提取结果的第一页。 有关使用查询参数的请求示例,请参阅发出请求。
发出请求
本节演示如何使用 JavaScript 和 Octokit.js 向 GitHub REST API 发出请求。 有关更详细的指南,请参阅 使用 REST API 和 JavaScript 编写脚本。
1. 设置
须安装 octokit
才能使用以下示例中所示的 Octokit.js 库。
- 安装
octokit
。 例如,npm install octokit
。 有关安装或加载octokit
的其他方式,请参阅 Octokit.js 自述文件。
2. 为请求选择终结点
-
选择要向其发出请求的终结点。 可以浏览 GitHub 的 REST API 文档,了解可用于与 GitHub 交互的终结点。
-
标识终结点的 HTTP 方法和路径。 将随请求一起发送这些内容。 有关详细信息,请参阅 HTTP 方法和路径。
例如,“创建问题”终结点使用 HTTP 方法和
POST
路径/repos/{owner}/{repo}/issues
。 -
标识任何必需的路径参数。 必需的路径参数显示在终结点路径的大括号
{}
中。 将每个参数占位符替换为想要的值。 有关详细信息,请参阅 Path。例如,“创建问题”终结点使用路径
/repos/{owner}/{repo}/issues
,路径参数为{owner}
和{repo}
。 要在 API 请求中使用此路径,请将{repo}
替换为想要创建新问题的存储库的名称,并将{owner}
替换为存储库所有者帐户的名称。
3. 创建访问令牌。
创建访问令牌对请求进行身份验证。 可以保存令牌并将其用于多个请求。 为令牌提供访问终结点所需的任何作用域或权限。 将会在 Authorization
标头中与请求一起发送此令牌。 有关详细信息,请参阅身份验证。
4. 使用 Octokit.js 发出请求
-
在脚本中导入
octokit
。 例如,import { Octokit } from "octokit";
。 有关导入octokit
的其他方式,请参阅 Octokit.js 自述文件。 -
首先,使用令牌创建
Octokit
的实例。 将YOUR-TOKEN
替换为令牌。JavaScript const octokit = new Octokit({ auth: 'YOUR-TOKEN' });
const octokit = new Octokit({ auth: 'YOUR-TOKEN' });
-
使用
octokit.request
执行请求。- 将 HTTP 方法和路径作为
request
方法的第一个参数发送。 有关详细信息,请参阅 HTTP 方法和路径。 - 将对象中的所有路径、查询和正文参数指定为
request
方法的第二个参数。 有关详细信息,请参阅参数。
在以下示例请求中,HTTP 方法为
POST
,路径为/repos/{owner}/{repo}/issues
,路径参数为owner: "octocat"
和repo: "Spoon-Knife"
,正文参数为title: "Created with the REST API"
和body: "This is a test issue created by the REST API"
。Note
如果使用的是 fine-grained personal access token,则必须将
octocat/Spoon-Knife
替换为属于你或所在组织的存储库。 令牌必须有权访问该存储库,并且对存储库问题具有读取和写入权限。 有关详细信息,请参阅“管理个人访问令牌”。JavaScript await octokit.request("POST /repos/{owner}/{repo}/issues", { owner: "octocat", repo: "Spoon-Knife", title: "Created with the REST API", body: "This is a test issue created by the REST API", });
await octokit.request("POST /repos/{owner}/{repo}/issues", { owner: "octocat", repo: "Spoon-Knife", title: "Created with the REST API", body: "This is a test issue created by the REST API", });
request
方法会自动传递Accept: application/vnd.github+json
标头。 若要传递其他标头或不同的Accept
标头,请将headers
属性添加到作为第二个参数传递的对象。headers
属性的值是将标头名称作为键并将标头值作为值的对象。例如,以下代码会发送值为
text/plain
的content-type
标头和值为2022-11-28
的X-GitHub-Api-Version
标头。JavaScript await octokit.request("GET /octocat", { headers: { "content-type": "text/plain", "X-GitHub-Api-Version": "2022-11-28", }, });
await octokit.request("GET /octocat", { headers: { "content-type": "text/plain", "X-GitHub-Api-Version": "2022-11-28", }, });
- 将 HTTP 方法和路径作为
使用响应
发出请求后,API 会返回响应状态代码、响应头,并可能返回响应正文。
关于响应代码和标头
每个请求都会返回 HTTP 状态代码,以指示响应是否成功。 有关响应代码的详细信息,请参阅 MDN HTTP 响应状态代码文档。
此外,响应会包含标头,以提供有关响应的更多详细信息。 以 X-
或 x-
开头的标头对于 GitHub 是自定义的。 例如,x-ratelimit-remaining
和 x-ratelimit-reset
标头会告知你在一段时间内可以发出的请求数。
使用 Octokit.js 发出请求时,request
方法会返回承诺。 如果请求成功,则承诺会解析为包含响应的 HTTP 状态代码 (status
) 和响应标头 (headers
) 的对象。 如果发生错误,则承诺会解析为包含响应的 HTTP 状态代码 (status
) 和响应标头 (response.headers
) 的对象。
如果发生错误,则可以使用 try/catch
块进行捕获。 例如,如果以下脚本中的请求成功,则脚本会记录状态代码和 x-ratelimit-remaining
标头的值。 如果请求未成功,脚本会记录状态代码、标头的 x-ratelimit-remaining
值和错误消息。
在以下示例中,将 REPO-OWNER
替换为存储库所有者的帐户的名称,并将 REPO-NAME
替换为存储库的名称。
try { const result = await octokit.request("GET /repos/{owner}/{repo}/issues", { owner: "REPO-OWNER", repo: "REPO-NAME", per_page: 2, }); console.log(`Success! Status: ${result.status}. Rate limit remaining: ${result.headers["x-ratelimit-remaining"]}`) } catch (error) { console.log(`Error! Status: ${error.status}. Rate limit remaining: ${error.headers["x-ratelimit-remaining"]}. Message: ${error.response.data.message}`) }
try {
const result = await octokit.request("GET /repos/{owner}/{repo}/issues", {
owner: "REPO-OWNER",
repo: "REPO-NAME",
per_page: 2,
});
console.log(`Success! Status: ${result.status}. Rate limit remaining: ${result.headers["x-ratelimit-remaining"]}`)
} catch (error) {
console.log(`Error! Status: ${error.status}. Rate limit remaining: ${error.headers["x-ratelimit-remaining"]}. Message: ${error.response.data.message}`)
}
关于响应正文
许多终结点会返回响应正文。 除非另外指定,否则响应正文会采用 JSON 格式。 空白字段包含为 null
,而不是被省略。 所有时间戳以 ISO 8601 格式返回 UTC 时间:YYYY-MM-DDTHH:MM:SSZ
。
与指定所需信息的 GraphQL API 不同,REST API 通常会返回比所需信息更多的信息。 如果需要,可以分析响应以拉取特定信息片段。
例如,可以获取每个问题的标题和创建者 ID: 在以下示例中,将 REPO-OWNER
替换为存储库所有者的帐户的名称,并将 REPO-NAME
替换为存储库的名称。
try { const result = await octokit.request("GET /repos/{owner}/{repo}/issues", { owner: "REPO-OWNER", repo: "REPO-NAME", per_page: 2, }); const titleAndAuthor = result.data.map(issue => {title: issue.title, authorID: issue.user.id}) console.log(titleAndAuthor) } catch (error) { console.log(`Error! Status: ${error.status}. Message: ${error.response.data.message}`) }
try {
const result = await octokit.request("GET /repos/{owner}/{repo}/issues", {
owner: "REPO-OWNER",
repo: "REPO-NAME",
per_page: 2,
});
const titleAndAuthor = result.data.map(issue => {title: issue.title, authorID: issue.user.id})
console.log(titleAndAuthor)
} catch (error) {
console.log(`Error! Status: ${error.status}. Message: ${error.response.data.message}`)
}
详细表示形式与摘要表示形式
响应可以包含资源的所有属性,也可以仅包含属性的子集,具体取决于是提取单个资源还是资源列表。
- 提取具体某个存储库等这样的_单个资源_时,响应通常会包含该资源的所有属性。 这就是资源的“详细”表示形式。
- 提取_资源列表_(如多个存储库的列表)时,响应将仅包含每个资源的属性子集。 这就是资源的“摘要”表示形式。
请注意,授权有时会影响表示形式中包含的详细信息量。
这是因为 API 提供的某些属性的计算成本很高,因此 GitHub 会从摘要表示形式中排除这些属性。 要获得这些属性,可以提取详细表示形式。
本文档提供每种 API 方法的示例响应。 示例响应说明了该方法返回的所有属性。
超媒体
所有资源都可以具有一个或多个链接到其他资源的 *_url
属性。 这些属性旨在提供明确的 URL,使适当的 API 客户端不需要自己构建 URL。 强烈建议 API 客户端使用这些属性。 这样做有助于开发者未来更容易升级 API。 所有 URL 都应该是适当的 RFC 6570 URI 模板。
然后,可以使用 uri_template gem 之类的内容来扩展这些模板:
>> tmpl = URITemplate.new('/notifications{?since,all,participating}')
>> tmpl.expand
=> "/notifications"
>> tmpl.expand all: 1
=> "/notifications?all=1"
>> tmpl.expand all: 1, participating: 1
=> "/notifications?all=1&participating=1"
后续步骤
本文演示了如何在存储库中列出和创建问题。 有关更多做法,请尝试对问题添加注释、编辑问题的标题或关闭问题。 有关详细信息,请参阅“创建问题注释”终结点和“更新问题”终结点。
有关可以使用的操作的详细信息,请参阅“REST 参考文档”。