常見問題及回報錯誤

Matt Gaunt

如果發生網路推送相關問題,偵錯或尋求協助並不容易。本文件將概述部分常見問題,以及在 Chrome 或 Firefox 中發現錯誤時應採取的行動。

在我們深入探討推送偵錯前,您可能會遇到下列問題:對 Service Worker 進行偵錯、檔案未更新、無法註冊,或通常只是異常行為。這份有關對服務工作站偵錯的優質文件,強烈建議您查看自己是否為 Service Worker 開發新手。

開發與測試網路推送時,必須完成兩個不同的階段。每個階段都有專屬的常見問題 / 問題:

  • 傳送訊息:確保訊息傳送成功。 您應該會收到 201 HTTP 代碼。如果您不符合以下條件:
    • 檢查授權錯誤:如果您收到授權錯誤訊息,請參閱授權問題部分
    • 其他 API 錯誤:如果您收到非 201 的狀態碼回應,請參閱 HTTP 狀態碼一節,瞭解問題原因的相關指引。
  • 接收訊息:如果您可以成功傳送訊息,但瀏覽器並未收到訊息:

如果您無法傳送及接收推送訊息,且本文件中的相關部分都無法協助偵錯,那麼您可能已經在推送機制中發現錯誤。在此情況下,請參閱「快速回報錯誤」一節,提交附有所有必要資訊的錯誤報告,以加快錯誤修正程序。

但在開始前,我想先說明 Firefox 和 Mozilla AutoPush Service 的錯誤訊息。如果您遇到困難,不確定是什麼問題,請在 Firefox 中進行測試,看看是否收到更有幫助的錯誤訊息。

授權問題

授權問題是開發人員開始使用網頁推送時最常遇到的問題之一。這通常是網站的應用程式伺服器金鑰 (亦稱為 VAPID 金鑰) 設定有問題。

如要同時在 Firefox 和 Chrome 中支援推送功能,最簡單的方法就是在 subscribe() 呼叫中提供 applicationServerKey。但缺點是前端和伺服器金鑰之間沒有差異,將導致授權錯誤。

使用 Chrome 和 FCM

針對使用 FCM 做為推送服務的 Chrome,您會收到 FCM 提供的 UnauthorizedRegistration 回應,以各種不同的錯誤,全部涉及應用程式伺服器金鑰。

下列情況中,您會收到 UnauthorizedRegistration 錯誤:

  • 如果您沒有在對 FCM 的要求中定義 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"
}

如果應用程式伺服器金鑰在使用者訂閱與簽署授權標頭時不同,系統會傳回 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 狀態碼清單,以及這些狀態碼代表網路推送代表的意義。

狀態碼 說明
429 要求數量過多。應用程式伺服器已達推送服務的頻率限制。服務的回應應包含「Try-After」標頭,指出可發出其他要求多久。
400 要求無效,其中一個標頭無效或格式不正確。
404 找不到。在這種情況下,您應該從後端刪除 PushSubscription,並等待有機會重新訂閱使用者。
410 消失。訂閱項目已失效,請從後端移除。只要在 PushSubscription 上呼叫「unsubscribe()」即可重現問題。
413 酬載大小上限。推送服務支援的最小酬載大小為 4096 個位元組 (或 4 KB)。放大實驗會導致這類錯誤。

如果這份清單未列出 HTTP 狀態碼,且錯誤訊息沒有幫助,請參閱網路推送通訊協定規格,確認系統是否參照狀態碼,以及該狀態碼的使用情境。

酬載加密問題

如果您可以成功觸發推送訊息 (例如傳送訊息至網路推送服務並接收 201 回應代碼),但推送事件從未在服務工作站中觸發,通常表示瀏覽器無法解密收到的訊息。

如果是這種情況,您會在 Firefox 的 DevTools 控制台中看到錯誤訊息,如下所示:

Firefox 開發人員工具和解密訊息。

如要在 Chrome 中檢查這是否為問題所在,請按照下列步驟操作:

  1. 前往 about://gcm-internals,按一下「開始錄製」按鈕。

Chrome GCM 內部記錄。

  1. 觸發推送訊息,並查看「Message Decryption Failure Log」下方的「Message Decryption Failure Log」。

GCM 內部解密記錄。

如果酬載的解密作業發生問題,系統會顯示類似上述的錯誤。(請注意詳細資料欄中的 AES-GCM decryption failed 訊息)。

如果遇到這個問題,您可從以下工具著手偵錯:

連線問題

如果您在 Service Worker 中未收到推送事件,也未看到任何解密錯誤,表示瀏覽器可能無法連線至推送服務。

在 Chrome 中,您可以藉由檢查 about://gcm-internals 中的「接收訊息記錄」(sic) 來檢查瀏覽器是否收到訊息。

GCM 內部訊息接收訊息記錄。

如果訊息未及時送達,請確認瀏覽器的連線狀態為 CONNECTED

GCM 內部連線狀態。

如果畫面不是「已連接」,您可能需要刪除目前的設定檔並建立新的設定檔。如果問題仍未解決,請按照下方建議提交錯誤報告。

發出錯誤報告

如果上述方法都無法協助您解決問題,而且沒有跡象顯示問題所導致,請針對發生問題的瀏覽器回報問題:

請使用 Chrome 回報問題:https://bugs.chromium.org/p/chromium/issues/list。如果是 Firefox,請前往 https://bugzilla.mozilla.org/ 回報問題。

如要提供完善的錯誤報告,你必須提供以下詳細資料:

  • 曾經使用過的瀏覽器 (例如 Chrome 50 版、Chrome 51 版、Firefox 50 版、Firefox 51 版)。
  • 可示範問題的 PushSubscription 範例。
  • 請加入任何範例要求 (即對推送服務的網路要求內容,包括標頭)。
  • 也包括網路要求中的所有範例回應。

如果您可以提供可重現的範例 (包括原始碼或代管網站),通常就能加快診斷和解決問題的速度。

後續步驟

程式碼研究室