Skip to main content

此版本的 GitHub Enterprise 已停止服务 2022-06-03. 即使针对重大安全问题,也不会发布补丁。 要获得更好的性能、改进的安全性和新功能,请升级到 GitHub Enterprise 的最新版本。 如需升级方面的帮助,请联系 GitHub Enterprise 支持

集成者最佳实践

构建一个能够可� 地与 GitHub Enterprise Server API 进行交互并为您的用户提供最佳体验。

有兴趣与 GitHub 平台集成吗? 与您志趣相投的大有人在。 本指南将帮助您构建能够为用户提供最佳体验确保与 API 进行可� 交互的应用程序。

确保安全接收从 GitHub 交付的有效负载

确保安全接收从 GitHub 发送的有效负载非常重要。 虽然有效负载中不会� 输个人信息,但泄露任何信息总是不好的。 有些信息可能比较敏感,包括提交者电子邮件地址或私有仓库的名称。

您可以采取以下� 个步骤来确保安全接收由 GitHub 交付的工作负载:

  1. 确保您的接收服务器在 HTTPS 连接上。 默认情况下,GitHub 在交付有效负载时会验证 SSL 证书。
  2. 提供密钥令牌以确保有效负载肯定来自 GitHub。 通过实施密钥令牌,您可以确保服务器接收的任何数据绝对来自 GitHub。 理想情况下,您应该为您服务的每个用户都提供一个不同的密钥令牌。 这� �,即使某个令牌被泄露,也不至于影响其他用户。

支持异步工作而非同步工作

GitHub 要求在收到 web 挂钩有效负载后 30 秒内做出集成响应。 如果您的服务需要更长的时间才能完成,则 GitHub 将终止连接,并且有效负载将丢失。

由于� 法预测您的服务完成速度,� 此您应该在后台作业中执行所有“实际工作”。 Resque(用于 Ruby)、RQ(用于 Python)或 RabbitMQ(用于 Java)是可以排队和处理后台作业的典型库。

请注意,即使在后台作业中执行工作,GitHub 仍要求您的服务器能够在三十秒内做出响应。 您的服务器需要通过发送某种响应来确认它收到了有效负载。 您的服务必须尽快对有效负载执行任何验证,以便您能够准确地报告您的服务器是否会继续处理请求。

响应 GitHub 时使用适当的 HTTP 状态代� �

每个 web 挂钩都有自己的“最近交付”部分,其中列出了部署是否成功。

最近交付视图

您应该使用适当的 HTTP 状态代� �来通知用户。 您可以使用 201202 等代� �来确认收到了不会处理的有效负载(例如,非默认分支交付的有效负载)。 将 500 错误代� �预留给灾难性故障。

向用户提供尽可能多的信息

用户可能会深入� �究您发回 GitHub 的服务器响应。 请确保您的信息清晰明了。

查看有效负载响应

遵循 API 发送给您的任何重定向

GitHub 在资源发生移动时会通过提供重定向状态代� �来明确告诉您。 您应该遵循这些重定向。 每个重定向响应都使用要转到的新 URI 来设置 Location � �头。 如果您收到了重定向,最好更新代� �以遵循新的 URI,以防您请求我们可能已� 除的� 效路径。

我们提供了 HTTP 状态代� �列表,供您在设计应用程序时参考以便遵循重定向。

不要手动解析 URL

通常,API 响应包含 URL 形式的数据。 例如,当请求仓库时,我们会发送一个名为 clone_url 的键,其中包含可用来克隆仓库的 URL。

为了应用程序的稳定性,您不应该尝试解析此数据,或者尝试猜测并构� 未来 URL 的� �式。 否则,如果我们决定更改该 URL,您的应用程序可能会中断。

例如,在处理分页结果时, 往往很想构�  URL - 在末尾追�  ?page=<number>。 要抑制这种冲动。 我们的分页指南提供了一些关于可� 跟踪分页结果的安全提示。

在处理事件之前检查事件类型和操作

有多种 web 挂钩事件类型,并且每个事件可以有多个操作。 随着 GitHub 功能集的增长,我们会不时添� 新的事件类型或向现有事件类型添� 新的操作。 请确保您的应用程序在进行任何 web 挂钩处理之前明确检查事件的类型和操作。 X-GitHub-Event 请求� �头可用于了解收到了哪个事件,以便进行适当处理。 同� �,有效负载具有顶层 action 键,可用于了解对相关对象采取了哪些操作。

例如,如果您已将 GitHub web 挂钩配置为“向我发送所有内容”,则在添� 新的事件类型和操作时,您的应用程序就会开始接收它们。 � 此,不建议使用任何类型的 catch-all else 子句。 以下面的代� �为例:

# Not recommended: a catch-all else clause
def receive
  event_type = request.headers["X-GitHub-Event"]
  payload    = request.body

  case event_type
  when "repository"
    process_repository(payload)
  when "issues"
    process_issues(payload)
  else
    process_pull_requests
  end
end

在此代� �实例中,如果收到 repositoryissues 事件,将会正确调用 process_repositoryprocess_issues 方法。 但是,任何其他事件类型都会导致调用 process_pull_requests。 当添� 新的事件类型时,这将导致不正确的行为 - 将以处理 pull_request 事件的方式来处理新的事件类型。

� 此,我们建议明确检查事件类型并采取相应行动。 在以下代� �示例中,我们明确检查 pull_request 事件,而 else 子句仅记录我们已收到新事件类型:

# Recommended: explicitly check each event type
def receive
  event_type = request.headers["X-GitHub-Event"]
  payload    = JSON.parse(request.body)

  case event_type
  when "repository"
    process_repository(payload)
  when "issues"
    process_issue(payload)
  when "pull_request"
    process_pull_requests(payload)
  else
    puts "Oooh, something new from GitHub: #{event_type}"
  end
end

由于每个事件也可以有多个操作,� 此建议对操作进行类似的检查。 例如,IssuesEvent 可能有� 个操作。 其中包括创建议题时的 opened、关闭议题时的 closed以及将议题分配给某人时的 assigned

与添� 事件类型一� �,我们可以向现有事件添� 新操作。 � 此,再次强调,在检查事件的操作时不要使用任何类型的 catch-all else 子句。 相反,我们建议像检查事件类型一� �明确检查事件操作。 下面的示例非常吻合我们在上文中针对事件类型的建议:

# Recommended: explicitly check each action
def process_issue(payload)
  case payload["action"]
  when "opened"
    process_issue_opened(payload)
  when "assigned"
    process_issue_assigned(payload)
  when "closed"
    process_issue_closed(payload)
  else
    puts "Oooh, something new from GitHub: #{payload["action"]}"
  end
end

在此示例中,在调用 process_closed 方法之前会先检查 closed 操作。 任何未识别的操作都会被记录以供将来参考。

处理 API 错误

尽管您的代� �从未引入漏洞,但您可能会发现在尝试访问 API 时遇到连续错误。

您应该确保与 API 正确交互,而不是忽略重复的 4xx5xx 状态代� �。 例如,如果某个端点请求一个字符串,而您向其� 递一个数值,则您将会收到 5xx 验证错误,并且您的调用不会成功。 同� �,试图访问未经授权或不存在的端点会导致 4xx 错误。

故意忽略重复的验证错误可能会导致您的应用程序� 滥用而被暂停。