常见问题和报告 bug

Matt Gaunt

当您遇到 Web 推送问题时,可能很难调试问题或寻求帮助。本文档概述了一些常见问题,以及如果您在 Chrome 或 Firefox 中发现 bug,应该怎么做。

在深入探讨调试推送之前,您可能会遇到调试 Service Worker 本身、文件未更新、无法注册或通常只是异常行为的问题。如果您是 Service Worker 开发新手,我强烈建议您阅读这篇关于调试 Service Worker 的精彩文档。

在开发和测试 Web 推送时,需要完成两个不同的阶段,每个阶段都有自己的一组常见问题:

  • 发送消息:确保消息发送成功。 您应该会收到 201 HTTP 代码。如果您不是:
  • 接收消息:如果您能够成功发送消息,但浏览器未收到消息:

如果您无法发送和接收推送消息,并且本文档中的相关部分无法帮助您调试问题,则您可能在推送机制本身中发现了 bug。在这种情况下,请参阅提交 bug 报告部分,提交包含所有必要信息的优质 bug 报告,以加快 bug 修复流程。

在开始之前,我想指出一点:Firefox 和 Mozilla AutoPush 服务具有出色的出错提示。如果您遇到问题,但不确定问题所在,请在 Firefox 中进行测试,看看是否能获得更有用的出错提示。

授权问题

授权问题是开发者在开始使用 Web 推送时遇到的最常见问题之一。这通常是网站的应用服务器密钥(也称为 VAPID 密钥) 配置问题。

在 Firefox 和 Chrome 中支持推送的最简单方法是在 subscribe() 调用中提供 applicationServerKey。缺点是,前端和服务器密钥之间的任何差异都会导致授权错误。

在 Chrome 和 FCM 上

对于使用 FCM 作为推送服务的 Chrome,您会收到来自 FCM 的 UnauthorizedRegistration 响应,其中包含一系列不同的错误,这些错误都涉及应用服务器密钥。

在以下任何情况下,您都会收到 UnauthorizedRegistration 错误:

  • 如果您未在向 FCM 发送的请求中定义 Authorization 标头。
  • 用于为用户订阅的应用密钥与用于为 Authorization 标头签名的密钥不匹配。
  • JWT 中的到期时间无效,即到期时间超过 24 小时或 JWT 已过期。
  • JWT 格式不正确或包含无效值。

完整的错误响应如下所示:

<html>
  <head>
    <title>UnauthorizedRegistration</title>
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <h1>UnauthorizedRegistration</h1>

    <h2>Error 400</h2>
  </body>
</html>

如果您在 Chrome 中收到此错误消息,请考虑在 Firefox 中进行测试,看看是否能提供更多有关问题的信息。

Firefox 和 Mozilla AutoPush

Firefox 和 Mozilla AutoPush 针对 Authorization 问题提供了一组易于理解的出错提示。

如果您的推送请求中不包含 Authorization 标头,您还会收到来自 Mozilla AutoPush 的 Unauthorized 错误响应。

{
  "errno": 109,
  "message": "Request did not validate missing authorization header",
  "code": 401,
  "more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes",
  "error": "Unauthorized"
}

如果 JWT 中的到期时间已过,您还会收到 Unauthorized 错误,并显示一条说明令牌已过期的消息。

{
  "code": 401,
  "errno": 109,
  "error": "Unauthorized",
  "more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes",
  "message": "Request did not validate Invalid bearer token: Auth expired"
}

如果用户订阅时和 Authorization 标头签名时的应用服务器密钥不同,系统会返回 Not Found 错误:

{
  "errno": 102,
  "message": "Request did not validate invalid token",
  "code": 404,
  "more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes",
  "error": "Not Found"
}

最后,如果 JWT 中存在无效值(例如,“alg”值为非预期值),您将收到来自 Mozilla AutoPush 的以下错误:

{
  "code": 401,
  "errno": 109,
  "error": "Unauthorized",
  "more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes",
  "message": "Request did not validate Invalid Authorization Header"
}

HTTP 状态代码

一系列问题都可能导致推送服务返回非 201 响应代码。下面列出了 HTTP 状态代码及其在 Web 推送方面的含义。

状态代码 说明
429 提交的请求数量过多。您的应用服务器已达到推送服务的速率限制。服务的响应应包含“Retry-After”标头,以指明在多长时间后可以发出另一个请求。
400 请求无效。您的某个标题无效或格式不正确。
404 未找到。在这种情况下,您应从后端删除 PushSubscription,并等待机会让用户重新订阅。
410 Gone。该订阅不再有效,应从您的后端中移除。这可以通过对 `PushSubscription` 调用 `unsubscribe()` 来重现。
413 载荷大小超出限制。推送服务必须支持的载荷大小下限为 4096 字节(或 4kb)。任何大于此大小的文件都可能导致此错误。

如果 HTTP 状态代码不在此列表中,并且出错提示没有帮助,请查看 Web 推送协议规范,了解是否引用了该状态代码以及何时可以使用该状态代码。

载荷加密问题

如果您可以成功触发推送消息(即向 Web 推送服务发送消息并收到 201 响应代码),但推送事件从未在 Service Worker 中触发,这通常表示浏览器未能解密收到的消息。

如果是这种情况,您应该会在 Firefox 的开发者工具控制台中看到如下所示的出错提示:

Firefox 开发者工具,其中显示了解密消息。

如需检查 Chrome 中是否存在此问题,请执行以下操作:

  1. 前往 about://gcm-internals,然后点击“Start Recording”(开始录制)按钮。

Chrome GCM 内部记录。

  1. 触发推送消息,然后在“消息解密失败日志”下查看。

GCM 内部解密日志。

如果载荷解密存在问题,您会看到类似于上文所示的错误。(请注意“详细信息”列中的 AES-GCM decryption failed 消息。)

如果这是您遇到的问题,可以使用以下几种工具来帮助调试加密:

连接问题

如果您在 Service Worker 中没有收到推送事件,也没有看到任何解密错误,则可能是浏览器无法连接到推送服务。

在 Chrome 中,您可以通过检查 about://gcm-internals 中的“Receive Message Log”(接收消息日志)来查看浏览器是否正在接收消息。

GCM 内部接收消息日志。

如果您没有及时看到消息到达,请确保浏览器的连接状态为 CONNECTED:

GCM 内部连接状态。

如果状态不是“CONNECTED”,您可能需要删除当前配置文件并创建新配置文件。如果仍无法解决问题,请按照以下建议提交 bug 报告。

提交 bug 报告

如果上述方法都无法解决您的问题,并且没有任何迹象表明问题可能是什么,请针对您遇到问题的浏览器提出问题:

对于 Chrome,您可以在此处提出问题: https://bugs.chromium.org/p/chromium/issues/list 对于 Firefox,您应在以下位置提出问题: https://bugzilla.mozilla.org/

为了提供良好的 bug 报告,您应提供以下详细信息:

  • 您测试过的浏览器(例如 Chrome 50、Chrome 51、Firefox 50、Firefox 51)。
  • 一个演示该问题的 PushSubscription 示例。
  • 请附上所有示例请求(即向推送服务发出的网络请求的内容,包括标头)。
  • 此外,还应包含网络请求中的任何示例响应。

如果您可以提供可重现的示例(源代码或托管网站),通常可以加快诊断和解决问题的速度。

下一步做什么

Codelab