常見問題及回報錯誤

Matt Gaunt

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

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

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

  • 傳送訊息:確認訊息傳送成功。您應該會收到 201 HTTP 代碼。如果您不是:
    • 檢查授權錯誤:如果您收到授權錯誤訊息,請參閱「授權問題」一節。
    • 其他 API 錯誤:如果您收到的回應狀態碼不是 201,請參閱「HTTP 狀態碼」一節,瞭解問題的原因。
  • 接收訊息:如果您可以順利傳送訊息,但瀏覽器未收到訊息,請按照下列步驟操作:

如果您無法傳送及接收推播訊息,且本文件中的相關章節無法協助您對問題進行偵錯,那麼您可能已在推播機制中找到錯誤。在這種情況下,請參閱「提交錯誤報告」一節,提交完整的錯誤報告,並附上所有必要資訊,以便加快錯誤修正程序。

在開始之前,我想強調一點,那就是 Firefox 和 Mozilla AutoPush Service 提供的錯誤訊息非常實用。如果遇到問題,且不確定問題所在,請在 Firefox 中進行測試,看看是否會顯示更實用的錯誤訊息。

授權問題

授權問題是開發人員在開始使用 Web Push 時最常遇到的問題之一。這通常是網站應用程式伺服器金鑰 (又稱為 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 傳送的要求過多,您的應用程式伺服器已達到推播服務的頻率限制。服務的回應應包含「Retry-After」標頭,指出何時可以提出其他要求。
400 要求無效,其中一個標頭無效或格式不正確。
404 找不到。在這種情況下,您應從後端刪除 PushSubscription,並等待重新訂閱使用者的機會。
410 消失。訂閱項目已失效,應從後端移除。您可以對 `PushSubscription` 呼叫 `unsubscribe()` 來重現這個問題。
413 酬載大小過大。推送服務必須支援的酬載大小下限為 4096 個位元組 (或 4 千位元組)。超過這個數字的任何值都會導致這個錯誤。

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

酬載加密問題

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

如果是這種情況,您應該會在 Firefox 的 DevTools 主控台中看到類似以下的錯誤訊息:

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 範例。
  • 提供任何示例要求 (也就是推播服務的網路要求內容,包括標頭)。
  • 並附上網路要求的回應範例。

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

後續步驟

程式碼研究室