有兴趣与 GitHub 平台集成吗? � 有很多同伴。 本指南将帮助� 构建能够为用户提供最佳体验并确保与 API 进行可� 交互的应用。
确保安全接收从 GitHub 交付的有效负载
请务必保护从 GitHub 发送的有效负载。 虽然有效负载中不会� 输个人信息(如密� �),但泄露任何信息总是不好的。 有些信息可能比较敏感,包括提交者电子邮件地址或私有仓库的名称。
您可以采取以下� 个步骤来确保安全接收由 GitHub 交付的工作负载:
- 确保您的接收服务器在 HTTPS 连接上。 默认情况下,GitHub 在交付有效负载时会验证 SSL 证书。
- 提供密钥令牌以确保有效负载肯定来自 GitHub。 通过实施密钥令牌,您可以确保服务器接收的任何数据绝对来自 GitHub。 理想情况下,� 应该为� 的服务的每个用户都提供一个不同的密钥令牌。 这� �,即使某个令牌被泄露,也不至于影响其他用户。
支持异步工作而非同步工作
GitHub 要求在收到 Webhook 有效负载后 30 秒内做出集成响应。 如果您的服务需要更长的时间才能完成,则 GitHub 将终止连接,并且有效负载将丢失。
由于� 法预测您的服务完成速度,� 此您应该在后台作业中执行所有“实际工作”。 Resque(用于 Ruby)、RQ(用于 Python)或 RabbitMQ(用于 Java)是可以处理后台作业的排队和处理的库的示例。
请注意,即使后台作业正在运行,GitHub 仍要求� 的服务器能够在三十秒内做出响应。 您的服务器需要通过发送某种响应来确认它收到了有效负载。 您的服务必须尽快对有效负载执行任何验证,以便您能够准确地报告您的服务器是否会继续处理请求。
响应 GitHub 时使用适当的 HTTP 状态代� �
每个 web 挂钩都有自己的“最近交付”部分,其中列出了部署是否成功。
您应该使用适当的 HTTP 状态代� �来通知用户。 � 可以使用 201
或 202
等代� �来确认收到了不会被处理的有效负载(例如,非默认分支交付的有效负载)。 针对灾难性故障预留 500
错误代� �。
向用户提供尽可能多的信息
用户可能会深入� �究您发回 GitHub 的服务器响应。 请确保您的信息清晰明了。
遵循 API 发送给您的任何重定向
GitHub 在资源发生移动时会通过提供重定向状态代� �来明确告诉您。 您应该遵循这些重定向。 每个重定向响应都使用要转到的新 URI 来设置 Location
� �头。 如果您收到了重定向,最好更新代� �以遵循新的 URI,以防您请求我们可能已� 除的� 效路径。
我们提供了 HTTP 状态代� �列表,� 在设计应用以遵循重定向时需要注意这些代� �。
不要手动解析 URL
通常,API 响应包含 URL 形式的数据。 例如,当请求存储库时,我们会发送一个名为 clone_url
的键,其中包含可用来克隆存储库的 URL。
为了应用程序的稳定性,您不应该尝试解析此数据,或者尝试猜测并构� 未来 URL 的� �式。 否则,如果我们决定更改该 URL,您的应用程序可能会中断。
例如,在处理分页结果时,人们往往很想构� 在末尾追� ?page=<number>
的 URL。 要抑制这种冲动。 我们的分页指南提供了一些关于可� 跟踪分页结果的安全提示。
在处理事件之前检查事件类型和操作
有多种 Webhook 事件类型,并且每个事件可以有多个操作。 随着 GitHub 功能集的增长,我们会不时添� 新的事件类型或向现有事件类型添� 新的操作。 请确保您的应用程序在进行任何 web 挂钩处理之前明确检查事件的类型和操作。 X-GitHub-Event
请求� �头可用于了解收到了哪个事件,以便进行适当处理。 同� �,有效负载具有顶层 action
键,可用于了解对相关对象采取了哪些操作。
例如,如果� 已将 GitHub Webhook 配置为“向我发送所有内容”,则在添� 新的事件类型和操作时,� 的应用程序就会开始接收它们。 � 此,不建议使用任何类型的 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
在此代� �实例中,如果收到 repository
或issues
事件,将会正确调用 process_repository
和 process_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 正确交互,而不是忽略重复的 4xx
和 5xx
状态代� �。 例如,如果某个终结点请求一个字符串,而� 向其� 递一个数值,则� 将会收到 5xx
验证错误,并且� 的调用不会成功。 同� �,试图访问未经授权或不存在的终结点会导致 4xx
错误。
故意忽略重复的验证错误可能会导致您的应用程序� 滥用而被暂停。