《Web 推送通知》系列翻譯 | 第十一篇:FAQ && 第十二篇:常見問題以及錯誤反饋

閱文前端團隊發表於2019-02-28

第十一篇:FAQ

原文地址:FAQ

譯文地址:FAQ

譯者:劉鵬

校對者:楊芯芯任家樂

為什麼推送在瀏覽器關閉的時候不工作

這個問題頗有爭議,主要是因為有一些場景使得這個問題比較難以追因和理解。

讓我們先從 Android 開始。Android 系統被設計成監聽推送訊息,一旦收到一條訊息,就會喚醒對應的 Android 應用來處理推送訊息,而不管這個應用是否關閉。

Android 上的任何瀏覽器和上述應用的表現是一致的,當接收到一條推送訊息的時候,瀏覽器會被喚醒,然後瀏覽器再喚醒你的 service worker,發出推送事件。

桌面作業系統則有細微差別。其中 Mac OS X 系統是最容易理解的,因為有一個視覺化的標記來輔助解釋不同的場景。

在 Mac OS X 系統上,你可以從 dock (列表中)的應用 icon 下方的標記來判斷一個程式是否在執行。

如果你對比一下下面 dock 中的兩個 Chrome icon,通過 icon 下面的標記我們可以知道左邊的那個正在執行,然而右邊的那個 Chrome 沒有在執行,因為缺少了下面的標記。

OS X 的示例

在桌面系統上接收推送訊息的情況下,當瀏覽器在執行的時候(即在 icon 下面有一個標記),你可以接收到訊息。

這意味著即使瀏覽器視窗沒有開啟,你仍然可以在你的 service worker 當中接收到推送訊息,因為瀏覽器正在後臺執行。

推送不能接收到的唯一情況就是瀏覽器被完全關閉了,即完全不在執行( icon 下沒有標記)。這同樣適用於 Windows 作業系統,雖然在 Windows 上判斷 Chrome 是否在後臺執行有一點複雜。

我如何讓使用者在點選推送訊息後,能夠全屏開啟我新增到桌面的 Web App?

在 Android 系統的 Chrome 瀏覽器上,Web App 可以被新增到桌面。當它在桌面被開啟的時候,可以在沒有位址列的全屏模式開啟,就像下面顯示的那樣。

桌面圖示全屏方式開啟

為了保持體驗的一致性,開發者也想使用者在點選通知之後能夠全屏開啟他們的 Web App。

Chrome 在某種程度上實現了這個特性,雖然你可能發現它不太靠譜並且難以追因。相關的實現細節如下:

在 Android 系統上,新增到桌面的網站在點選推送訊息的時候,應該被允許以 standalone(獨立) 模式開啟。然而即使網站被新增到了桌面,由於 Chromium 依然不能檢測到這些網站是否在桌面上。我們啟發式地採用了下面這種方法:那些在最近 10 天內從桌面啟動過的網站,點選通知後將以 standalone 模式開啟。-- Chrome Issue

這就意味著,除非你的使用者足夠頻繁地通過桌面訪問你的站點,否則的話你的通知只會開啟一個普通的瀏覽器 UI。

這個問題將進一步解決。

注意: 這個只是 Chrome 的表現,其它瀏覽器也會有一些不同。如果你有任何需要討論的,請儘管提出 issue

為什麼這個比 web sockets 要好?

即使瀏覽器視窗是關閉的,service worker 依然可以工作。而 web socket 只有在瀏覽器和網頁保持開啟的狀態下才能正常工作。

GCM、 FCM、 Web 推送 和 Chrome 是怎麼回事?

這個問題有很多方面,最簡單的解釋方法是逐步介紹 Web 推送和 Chrome 的歷史。(別擔心,很短)

2014 年 12 月

當 Chrome 首次實現 Web 推送時,是使用 Google Cloud Messaging(GCM)來支援從伺服器向瀏覽器傳送推送訊息的。

但這不是 Web 推送。早期的 Chrome 和 GCM 並不是“真正的” Web 推送有以下幾個原因:

  • GCM 要求開發人員在 Google Developers Console 上註冊帳戶。
  • Chrome 和 GCM 需要一個特殊的由 Web 應用程式共享的傳送者 ID,來正確地設定訊息。
  • GCM 的伺服器接收的是自定義的 API 請求,而非 Web 標準。
2016 年 7 月

7月,Web 推送中的一項新功能釋出 - Application Server Keys(即規範中的 VAPID )。Chrome 在支援此新 API 時,棄用了 GCM,改用 Firebase Cloud Messaging(FCM)作為訊息傳遞服務。這很重要,原因如下:

  • Chrome 和 Application Server Keys 不需要使用 Google 或 Firebase 設定任何型別的專案,就可以正常工作。
  • FCM 支援 Web 推送協議,這是所有 Web 推送服務都支援的 API。這意味著無論瀏覽器使用什麼推送服務,你只需傳送相同型別的請求,它就會推送訊息。
為什麼現在令人困惑?

現在已經存在的關於 Web 推送的內容中存在大量混淆,其中大部分內容都引用了 GCM 或 FCM。 如果內容用了 GCM,你可以將其視為是過時內容的標誌,或者它太過針對於 Chrome。(我在一些舊的文章中也犯了這個錯誤)

因此,你應該將 Web 推送視為瀏覽器的一部分,瀏覽器使用推送服務來管理髮送和接收訊息,其中推送服務將接受符合“Web 推送協議”的請求。如果按照這樣進行思考,你就可以無視瀏覽器及其使用的推送服務的干擾,並直接開始工作了。

本書的編寫專注於 Web 推送的標準方法,所以有意忽略其他任何內容。

Firebase 有一個 JavaScript SDK,它是什麼以及為什麼會存在?

對於那些已經發現 Firebase Web SDK 且注意到它有 JavaScript 版本的訊息傳遞 API 的人,可能會想知道它與 Web 推送的區別。

訊息傳遞 SDK(Firebase Cloud Messaging JS SDK)在幕後做了一些工作以便更輕鬆地實現 Web 推送。

  • 只需要關心 FCM 令牌(僅僅是一個字串),而不必關心 PushSubscription 及其各個欄位。
  • 通過使用每個使用者的令牌,你可以使用專有的 FCM API 來觸發推送訊息。此 API 不需要加密有效負載,可以在 POST 請求 body 中傳送普通(未加密)的文字有效載荷。
  • FCM 的專有 API 支援自定義功能,例如 FCM 主題(儘管相關文件很少,但它也可以在 Web 上執行)。
  • 最後,FCM 支援 Android、iOS 和 Web,因此對於一些團隊來說,在現有專案中更容易使用。

其實它在底層使用的還是 Web 推送,但是目的就是把 Web 推送抽象出來。

就像我在上一個問題中所說的那樣,如果將 Web 推送視為瀏覽器加上推送服務,那麼你可以將 Firebase 中 的 Messaging SDK 視為一個簡化的 Web 推送的庫。

第十一篇:Web 推送:常見問題以及錯誤反饋

原文地址:common issues and reporting bugs

譯文地址:Web 推送:常見問題以及錯誤反饋

譯者:劉文濤

校對者:張卓 劉鵬

當你使用網路推送遇到問題時,可能很難去除錯這個問題或尋求幫助。 本文將概述一些常見問題以及如果你在 Chrome 或 Firefox 中發現錯誤,應該怎麼去做。

在我們深入除錯推送之前,你可能遇到 service workers 本身的問題,檔案未更新,未註冊或一般的異常行為。 關於除錯 service workers 的文件非常完善,如果你是初次使用 service worker 開發的話 ,我強烈建議你去閱讀一下。

在開發和測試 Web 推送的兩個階段中,每個階段都遇到獨有的一些常見問題。

  • 傳送訊息: 首先應確保傳送訊息成功。正確返回的 HTTP 狀態碼應該是 201。 如果不是:
    • 檢查授權錯誤: 如果收到授權錯誤訊息,請參閱下面 “授權相關問題部分"。
    • 其他API錯誤: 如果收到非201狀態程式碼,請參閱下面的“HTTP 狀態程式碼部分“以獲取有關問題原因的指導。
  • 接收訊息: 如果你能夠成功傳送訊息,但在瀏覽器上未收到訊息:
    • 檢查加密問題: 請參閱下面的“有效負載加密問題部分“。
    • 檢查連線問題: 如果是在 Chrome 上出的問題,可能與連線有關。 可參閱下面的“連線問題”部分。

如果無法傳送和接收推送訊息,並且本文件中的相關部分不能幫助你除錯問題,那麼你可能發現了推送機制本身的一個 Bug。在這種情況下,請參閱 “如何提交錯誤報告”部分,提交一份包含所有重要資訊的錯誤報告,以加快錯誤修復過程。

在提交錯誤報告之前我想說的一件事是:Firefox 和 Mozilla 自動推送服務給了很多有用的錯誤資訊。 如果你遇到問題並且不確定是什麼問題的時候,那麼請在 Firefox 中進行測試,看看是否可以收到了更有用的錯誤訊息。

授權問題

授權問題是開發人員在開始使用 Web 推送時遇到的最常見問題之一。 這通常是配置站點應用伺服器金鑰(又名 VAPID 金鑰)的問題。

在 Firefox 和 Chrome 中,支援推送的最簡單方法是在 subscribe() 呼叫中提供 applicationServerKey。這樣做不好的是,前端和伺服器金鑰之間的任何差異都會導致授權錯誤。

在 Chrome + 雲訊息傳遞FCM

對於使用 FCM 作為推送服務的 Chrome,你將收到來自 FCM:關於UnauthorizedRegistration response【未經授權註冊】 的一系列不同的錯誤,所有錯誤都涉及應用程式伺服器金鑰。

在以下任何一種情況下,你都會收到一個 UnauthorizedRegistration 錯誤:

  • 沒有在 FCM 的請求中定義 Authorization header。
  • 用於訂閱使用者的應用程式金鑰與用於簽署 Authorization header 的金鑰不匹配。
  • 你的 JWT【Json web token】到期無效,即超過 24 小時或 JWT 已過期。
  • JWT 異常或值無效。

完整的錯誤響應如下所示:

<HTML>\n<HEAD>\n<TITLE>UnauthorizedRegistration</TITLE>\n</HEAD>\n<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\n<H1>UnauthorizedRegistration</H1>\n<H2>Error 400</H2>\n</BODY>\n</HTML>\n
複製程式碼

如果你在 Chrome 中收到此錯誤訊息,可以考慮在 Firefox 中進行測試,看看它是否能夠提供有關此問題的更多資訊。

Firefox and Mozilla 自動推送

Firefox 和 Mozilla 自動推送 為 Authorization 授權問題提供了一系列非常友好的錯誤提示。

如果你的推送請求中未包含 Authorization header,你將會收到來自 Mozilla 自動推送的 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"  
}
複製程式碼

如果使用者訂閱時的應用伺服器金鑰和授權 header 頭簽名時的應用伺服器金鑰不同,則會返回未找到錯誤

{  
	"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 自動推送中收到以下錯誤資訊:

{  
	"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 推送相關的問題描述。

Status Code Description
429 請求太多。 應用程式伺服器推送服務達到了速率限制。 推送服務的響應當中應該包括了 “Retry-After" 標頭,來指示你需要等待多久來傳送另一個請求。
400 無效的請求。 你的某一個 Header 無效或格式不正確。
404 沒有找到。訂閱已過期。在這種情況下,你應該從你的後臺刪除 PushSubscription,並且等待一個時機再次給使用者訂閱。
410 失效. 訂閱不再有效,應該從你的後臺移除。這可以在 `PushSubscription` 上通過呼叫 `unsubscribe()` 方法來移除。
413 有效載荷大小太大。 推送服務必須支援的最小大小有效負載是 4096 位元組(或4kb)。 任何更大的大小都可能導致此錯誤。

如果 http 狀態碼不在此列表中且錯誤資訊沒有給到幫助,可以檢視 Web Push Protocol spec (Web 推送協議),看下這個狀態碼是在哪些場景下觸發。

有效負載加密問題

如果成功觸發推送訊息(即向 Web 推送服務傳送訊息並接收到 201 響應碼),但推送事件沒有在 service worker 中觸發,這通常表示瀏覽器無法解密其接收到的訊息。

如果是這種情況,可以在 Firefox 的 DevTools 控制檯中看到一條錯誤訊息,如下所示:

Firefox DevTools with decryption message

要檢查 Chrome 中是否存在此問題,請執行以下操作:

  1. 位址列輸入 chrome://gcm-internals ,進入並點選“Start Recording【開始錄製】”按鈕。
Chrome GCM internals record
  1. 觸發一個推送訊息,看下“訊息解密失敗日誌”。
GCM internals decryption log

如果有效負載的解密存在問題,將看到類似於上面顯示的錯誤。 (請注意詳細資訊列中的 AES-GCM decryption failed 訊息。)

如果是這個問題,有一些工具可以幫助你除錯加密:

連線問題

如果你沒有在 service worker 中收到推送事件,並且沒有看到任何解密錯誤,可能是瀏覽器無法連線到推送服務。

在 Chrome 中,可以通過頁面:chrome://gcm-internals 中的“接收訊息日誌”模組來檢查瀏覽器是否正在接收訊息。

GCM internals receive message log

如果沒有及時看到訊息,請確保你的瀏覽器的連線狀態為 CONNECTED,如下圖所示:

GCM internals connection state

如果連結狀態不是 “CONNECTED”,可能需要刪除當前的配置檔案並建立一個新的。 如果仍然無法解決問題,請按照下面章節的建議提出錯誤報告。

錯誤反饋

如果上面的方式都不能解決你的問題,並且沒有跡象表明問題可能是什麼,請根據你遇到問題的瀏覽器提出問題:

對於 Chrome,你可以在此處反饋問題:bugs.chromium.org/p/chromium/…

對於 Firefox,你可以在此處反饋問題: bugzilla.mozilla.org/

如何提供一個好的的錯誤報告,你應該做到以下幾點:

  • 你測試的瀏覽器版本(例如 Chrome 版本50,Chrome 版本51,Firefox 版本50,Firefox 版本51)。
  • 給出一個例子,可以重現這個問題;
  • 報告中應該包括請求的所有資訊(即對推送服務的網路請求的內容[包含 header])。
  • 報告中應該包括網路請求的返回的響應資料。

如果你能提供一個可重現的例子,或者原始碼或託管網站,它經常可以讓我們更快速地診斷和解決問題。

更多分享,請關注YFE:

《Web 推送通知》系列翻譯 | 第十一篇:FAQ && 第十二篇:常見問題以及錯誤反饋

上一篇:《Web 推送通知》系列翻譯 | 第九篇:通知行為 && 第十篇:常用的通知模式

相關文章