常見問題及回報錯誤

Matt Gaunt

遇到網頁推送問題時,可能很難對問題進行偵錯或尋求協助。本文件將概述一些常見問題,以及您在 Chrome 或 Firefox 中發現錯誤時應採取的行動。

在我們深入探討推送偵錯之前,您可能會遇到偵錯服務工作者本身、檔案未更新、註冊失敗或一般不尋常行為的問題。如果您是服務工作程式開發新手,強烈建議您查看服務工作程式偵錯相關的絕佳文件

開發和測試網路推播時,需要檢查兩個不同的階段,每個階段都有各自的常見問題:

  • 傳送訊息:請確認訊息傳送成功。您應該會收到 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"
}

如果應用程式伺服器金鑰與使用者訂閱時間與簽署 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 狀態碼清單,以及這些代碼與網路推送相關的含義。

狀態碼 說明
429 傳送的要求過多,您的應用程式伺服器已達到推播服務的頻率限制。服務的回應應包含「重試 - 之後」標頭,以指出提出另一項要求之前的時間。
400 要求無效,其中一個標頭無效或格式不正確。
404 找不到。在這種情況下,您應該從後端刪除 PushSubscription 並等待重新訂閱使用者的機會。
410 消失。訂閱項目已失效,應從後端移除。您可以對 `PushSubscription` 呼叫 `unsubscribe()` 來重現這個問題。
413 酬載大小過大。推送服務必須支援的酬載大小下限為 4096 個位元組 (或 4 千位元組)。任何數值過大都可能會造成這項錯誤。

如果 HTTP 狀態碼不在這個清單中,且錯誤訊息無法提供任何幫助,請查看 Web Push Protocol 規格,瞭解系統是否參照了狀態碼,以及何時可以使用該狀態碼。

酬載加密問題

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

如果是這種情況,Firefox 開發人員工具控制台中應會顯示錯誤訊息,如下所示:

Firefox 開發人員工具,顯示解密訊息。

如要確認 Chrome 是否有這個問題,請按照下列步驟操作:

  1. 前往 about://gcm-internals,然後按一下「Start Recording」(開始錄製) 按鈕。

Chrome GCM 內部記錄。

  1. 觸發推播訊息,然後查看「訊息解密失敗記錄」。

GCM 內部解密記錄。

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

如果是這個問題,您可以使用以下幾個工具進行加密偵錯:

連線問題

如果您未在服務工作者中收到推播事件,且未看到任何解密錯誤,則瀏覽器可能無法連線至推播服務。

在 Chrome 中,您可以查看 about://gcm-internals 中的「Receive Message Log」(訊息接收記錄),檢查瀏覽器是否正在接收訊息。

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 範例。
  • 請加入所有要求範例 (即傳送至推送服務的網路要求內容,包括標頭)。
  • 請一併附上來自網路要求的所有範例回應。

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

後續步驟

程式碼研究室