# Webhook 疑难解答

了解如何诊断和解决 Webhook 的常见错误。

## 缺少 Webhook 交付

如果未收到预期的 Webhook 交付，则应确定缺少交付的点。

1. 触发预期会导致 Webhook 交付的事件。 例如，如果你的 Webhook 是订阅 `issues` 事件的存储库 Webhook，则可以就该存储库提出问题。

2. 查看 Webhook 的最新交付日志。 若要了解如何为每个 Webhook 类型执行此操作，请参阅“[查看 web 挂钩交付](/zh/enterprise-server@3.22/webhooks/testing-and-troubleshooting-webhooks/viewing-webhook-deliveries)”。

   如果最新的交付日志不包括与在上一步中触发的 Webhook 事件对应的交付，则 GitHub 未尝试交付。 要确定原因：

   1. 请等候几分钟，然后再次查看。 Webhook 交付可能需要几分钟才会显示。

   2. 请确保在配置 Webhook 的位置触发了事件。 例如，如果 Webhook 是存储库 Webhook，请确保在配置 Webhook 的同一存储库中触发了该事件。

   3. 确保 Webhook 已订阅触发的事件。 例如，如果在提出问题时需要 Webhook 交付，请确保 Webhook 已订阅该 `issues` 事件。

   4. 确保 Webhook 处于活动状态。 有关详细信息，请参阅“[禁用网络钩子 (Webhook)](/zh/enterprise-server@3.22/webhooks/using-webhooks/disabling-webhooks)”。

   5. 请确保您的 Webhook 不受到 OAuth app 访问限制的影响。 如果你的 Webhook 是由 OAuth app 代表授权 OAuth app 的用户创建的，那么如果 Webhook 是受 OAuth app 限制访问的组织或组织存储库 Webhook，则该 Webhook 将被自动禁用。 有关详细信息，请参阅 GitHub Free 文档中的 [关于 OAuth 应用访问限制](/zh/organizations/managing-oauth-access-to-your-organizations-data/about-oauth-app-access-restrictions)。

   6. 查看事件是否达到了已记录的限制。 例如，如果一次推送三个以上标记，则该推送不会触发 `push` 事件。 若要详细了解每个事件记录的限制，请参阅“[Webhook 事件和有效负载](/zh/enterprise-server@3.22/webhooks/webhook-events-and-payloads)”。

   7. 前往 [githubstatus.com](https://www.githubstatus.com/) 查看 Webhook 的状态。

   如果最新的交付日志显示交付出错，则 GitHub 虽然尝试交付，但交付失败。 这通常是由于服务器出现问题。 可以参考以下部分来帮助解决特定错误。

3. 查看服务器的日志。 日志中的信息取决于服务器运行的用于处理 Webhook 传递的代码。 为了帮助你诊断服务器上的问题，可能需要向代码添加其他日志语句。

## 不能超过 250 个 Webhook

针对每个事件类型，最多可以创建 250  个存储库、组织或全局
Webhook。 如果尝试创建更多内容，你将收到一条错误，其中指出不能超过 250 个 Webhook。

如果您需要的 Webhook 数量超过 250，可以运行一个代理来接收来自 GitHub 的 Webhook，并将其转发至无限数量的目标 URL。

## 不支持 localhost 作为 URL 主机

不能使用 `localhost` 或 `127.0.0.1` 用作 Webhook URL。

如果要将 Webhook 交付到本地服务器进行测试，可以使用 Webhook 转发服务。 有关详细信息，请参阅“[测试 web 挂钩](/zh/enterprise-server@3.22/webhooks/testing-and-troubleshooting-webhooks/testing-webhooks)”或访问 <https://smee.io/。>

## 无法连接到主机

当 `failed to connect to host` 试图进行 Webhook 传递时，如果 GitHub 无法将 Webhook 的 URL 解析为 IP 地址，或者网络限制阻止连接到主机，则会发生此错误。

若要检查主机名是否解析为 IP 地址，可以使用 `nslookup`。 例如，如果有效负载 URL 为 `https://octodex.github.com/webhooks`，则可以运行 `nslookup octodex.github.com`。 如果主机名无法解析为 IP 地址，则 nslookup 命令将指示服务器找不到主机名。

应确保服务器允许与 GitHub 的 IP 地址建立连接。 可以使用 `GET /meta` 端点来查找 GitHub 的当前 IP 地址列表。 有关详细信息，请参阅“[元数据的 REST API 端点](/zh/enterprise-server@3.22/rest/meta/meta#get-github-meta-information)”。 GitHub 有时会对其 IP 地址进行更改，因此应定期更新 IP 允许列表。

## 无法连接到网络

`failed to connect to network` 错误表示当 GitHub 尝试传递 Webhook 时，服务器拒绝了连接。

应确保服务器允许与 GitHub 的 IP 地址建立连接。 可以使用 `GET /meta` 端点来查找 GitHub 的当前 IP 地址列表。 有关详细信息，请参阅“[元数据的 REST API 端点](/zh/enterprise-server@3.22/rest/meta/meta#get-github-meta-information)”。 GitHub 有时会对其 IP 地址进行更改，因此应定期更新 IP 允许列表。

## 已超时

`timed out` 错误指示 GitHub 未在 30 秒内收到来自服务器的传送 Webhook 的响应。

服务器在收到 Webhook 请求后应该在 30 秒内返回 2xx 响应。 如果服务器的响应时间超过该时间，则 GitHub 将终止连接，并认为传递失败。

为了及时响应，您可能需要设置一个队列来异步处理 Webhook 负载。 服务器可以在收到 Webhook 时进行响应，然后在后台处理有效负载，而不阻止未来的 Webhook 传递。 例如，可以使用 [Hookdeck](https://hookdeck.com) 等服务或 [Resque](https://github.com/resque/resque/) (Ruby)、[RQ](http://python-rq.org/) (Python) 或 [RabbitMQ](http://www.rabbitmq.com/) 等库。

## 对等证书无法通过给定的 CA 证书进行验证

此错误表示存在与服务器证书相关的问题。 最常见的问题如下：

* 服务器正在使用自签名证书。
* 建立连接时，服务器不会发送完整的证书链。

为了帮助诊断问题，可以使用 SSL 实验室中的 [SSL 服务器测试](https://www.ssllabs.com/ssltest/analyze.html)。 此服务只能使用 HTTPS（端口 443）的默认端口，并且只能使用可通过 Internet 访问的服务器。

还可以使用 `openssl` 帮助诊断问题。 为此，请在终端中运行 `openssl s_client -connect HOST:PORT`。 将 `HOST` 替换为服务器的主机名，将 `PORT` 替换为端口。 例如，`openssl s_client -connect example.com:443`。 若要识别问题，请在输出中查找 `verify error`。

## HTTP 响应无效

当服务器返回 4xx 或 5xx 状态以响应 GitHub 发送的 Webhook 请求时，会发生 `invalid HTTP response` 错误。

应将服务器配置为返回 2xx 状态。 如果服务器返回 4xx 或 5xx 状态，GitHub 会将交付记录为失败。

## Webhook 交付无序

GitHub 可能会按与事件发生顺序不同的顺序交付 Webhook。 如果需要知道事件何时相对于另一个事件发生，则应使用交付有效负载中包含的时间戳。

## Webhook 交付不是即时的

Webhook 交付可能需要在几分钟后才能交付并显示在最新的交付日志中。 在判断 Webhook 交付失败之前，请先等待几分钟，然后再进行检查。

## 签名验证失败

应使用 Webhook 机密和 `X-Hub-Signature-256` 标头来验证 Webhook 交付是否来自 GitHub。 有关详细信息，请参阅“[验证 Webhook 交付](/zh/enterprise-server@3.22/webhooks/using-webhooks/validating-webhook-deliveries)”。

如果确定有效负载来自 GitHub 但签名验证失败：

* 请确保已为 Webhook 配置机密。 如果尚未为 Webhook 配置机密，`X-Hub-Signature-256` 标头将不存在。 有关为 Webhook 配置机密的详细信息，请参阅“[测试 Webhook](/zh/enterprise-server@3.22/webhooks/using-webhooks/editing-webhooks)”。
* 请确保使用正确标头。 GitHub 建议使用 `X-Hub-Signature-256` 标头，该标头使用 HMAC-SHA256 算法。 `X-Hub-Signature` 标头使用 HMAC-SHA1 算法，仅用于旧用途。
* 请确保使用正确算法。 如果使用 `X-Hub-Signature-256` 标头，则应使用 HMAC-SHA256 算法。
* 请确保使用正确的 Webhook 机密。 如果不知道 Webhook 机密的值，可以更新 Webhook 机密。 有关详细信息，请参阅“[测试 Webhook](/zh/enterprise-server@3.22/webhooks/using-webhooks/editing-webhooks)”。
* 在验证之前，请确保不会修改有效负载和标头。 例如，如果使用代理或负载均衡器，请确保代理或负载均衡器不会修改有效负载或标头。
* 如果你的语言和服务器实现指定了字符编码，请确保将有效负载处理为 UTF-8。 Webhook 有效负载可以包含 unicode 字符。