使用瀏覽器的 Reporting API 上報站點錯誤
Reporting API 定義了一個新的 HTTP Header,Report-To,它讓 Web 開發(fā)人員以自定義的方式來將瀏覽器的警告和錯誤發(fā)送到指定服務(wù)器。例如 CSP違規(guī), Feature Policy 違規(guī),使用了廢棄API,瀏覽器崩潰和網(wǎng)絡(luò)錯誤等是可以使用 Reporting API 收集的一些信息。
簡介
有些錯誤你可能在開發(fā)的時候永遠(yuǎn)都看不到,但是生產(chǎn)環(huán)境中可能出現(xiàn),因為不同的用戶、不同的使用環(huán)境、不同的瀏覽器都有可能出現(xiàn)意想不到的問題。
例如,假設(shè)你的新站點依賴 document.write() 來加載關(guān)鍵腳本。來自世界各地的新用戶要訪問你的站點,但是他們使用的連接可能比你的測試環(huán)境要慢得多。你所不知道的是,你的網(wǎng)站開始為他們中斷,因為 Chrome 瀏覽器干涉阻止2G網(wǎng)絡(luò)上的 document.write() 。如果沒有 Reporting API ,就無法知道你寶貴的用戶是否發(fā)生了這種情況。
Reporting API 可幫助捕獲整個站點中潛在的錯誤。進行設(shè)置可讓你對你的網(wǎng)站更放心,當(dāng)真實用戶訪問你的網(wǎng)站時,沒有發(fā)生任何可怕的事情。如果當(dāng)他們確實遇到無法預(yù)料的錯誤時,你會知道的。
Report-To Header
Reporting API 定義了一個新的 HTTP Header ,它的值是一個對象,它描述了瀏覽器要向以下對象報告錯誤的信息:
- Report-To: {
- "max_age": 10886400,
- "endpoints": [{
- "url": "https://analytics.provider.com/browser-errors"
- }]
- }
注意:如果你的 endpoints URL 與你的站點位于不同的來源,則 endpoints 應(yīng)支持CORS 請求。(例如Access-Control-Allow-Origin: *; Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS; Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With
配置多個端點
單個響應(yīng)可以通過發(fā)送多個 Report-To 標(biāo)頭來一次配置多個端點:
- Report-To: {
- "group": "default",
- "max_age": 10886400,
- "endpoints": [{
- "url": "https://example.com/browser-reports"
- }]
- }
- Report-To: {
- "group": "csp-endpoint",
- "max_age": 10886400,
- "endpoints": [{
- "url": "https://example.com/csp-reports"
- }]
- }
或?qū)⑺鼈兘M合成一個HTTP標(biāo)頭:
- Report-To: {
- "group": "csp-endpoint",
- "max_age": 10886400,
- "endpoints": [{
- "url": "https://example.com/csp-reports"
- }]
- },
- {
- "group": "network-endpoint",
- "max_age": 10886400,
- "endpoints": [{
- "url": "https://example.com/network-errors"
- }]
- },
- {
- "max_age": 10886400,
- "endpoints": [{
- "url": "https://example.com/browser-errors"
- }]
- }
發(fā)送 Report-To 標(biāo)頭后,瀏覽器將根據(jù)端點的 max_age 值緩存端點,并將所有這些討厭的控制臺警告/錯誤發(fā)送到你的URL。
字段說明
- group:(選填)上報端點名稱,如果 group 未指定名稱,則為上報端點指定名稱 default。
- max_age:(必填)一個非負(fù)整數(shù),以秒為單位定義上報端點的生存期。
- endpoints:(必填)JSON對象數(shù)組,用于指定報告收集器的實際URL。
- include_subdomains:(選填)指定在報告錯誤時是否考慮子域。
瀏覽器如何發(fā)送報告
瀏覽器會定期批處理報告,并將其發(fā)送到你配置的報告URL。為了發(fā)送報告,瀏覽器發(fā)出一個POST 請求, Content-Type: application/reports+json 并帶有一個正文,其中包含捕獲的警告/錯誤數(shù)組。
下面是一個CSP報告的示例:
- POST /csp-reports HTTP/1.1
- Host: example.com
- Content-Type: application/reports+json
- [{
- "type": "csp",
- "age": 10,
- "url": "https://example.com/vulnerable-page/",
- "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
- "body": {
- "blocked": "https://evil.com/evil.js",
- "directive": "script-src",
- "policy": "script-src 'self'; object-src 'none'",
- "status": 200,
- "referrer": "https://evil.com/"
- }
- }, }
- ...
- }]
Reporting API 旨在與你的Web應(yīng)用配合使用。瀏覽器捕獲,排隊和批處理,然后在最合適的時間自動發(fā)送報告。報告是由瀏覽器在內(nèi)部發(fā)送的,因此使用 Reporting API 時幾乎沒有性能問題(例如與應(yīng)用程序發(fā)生網(wǎng)絡(luò)爭用)。也沒有辦法控制瀏覽器何時發(fā)送排隊的報告。
上報 CSP
在以前,我們可以給 CSP 增加一個 report-uri 來上報問題:
- Content-Security-Policy: ...; report-uri https://example.com/csp-reports
- Content-Security-Policy-Report-Only: ...; report-uri https://example.com/csp-report
下面是一個使用 Report-To 上報 CSP 問題的例子:
- Content-Security-Policy-Report-Only: ...; report-to csp-endpoint
- Report-To: {
- ...
- }, {
- "group": "csp-endpoint",
- "max_age": 10886400,
- "endpoints": [{
- "url": "https://example.com/csp-reports"
- }]
- }
為了向后兼容,請與 report-uri 一起繼續(xù)使用 report-to。換句話說:Content-Security-Policy: ...; report-uri https://example.com/csp-reports; report-to groupname。支持的瀏覽器 report-to 將使用它代替report-uri。
上報網(wǎng)絡(luò)錯誤
網(wǎng)絡(luò)錯誤日志(NEL)規(guī)范定義了一種從源頭收集客戶端網(wǎng)絡(luò)錯誤的機制。它使用新的 NEL HTTP 響應(yīng)頭來設(shè)置,告訴瀏覽器收集網(wǎng)絡(luò)錯誤,然后與 Reporting API 集成,將錯誤報告給服務(wù)器。
要使用 NEL,首先使用一個使用命名組的收集器設(shè)置報告頭:
- Report-To: {
- ...
- }, {
- "group": "network-errors",
- "max_age": 2592000,
- "endpoints": [{
- "url": "https://analytics.provider.com/networkerrors"
- }]
- }
接下來,發(fā)送NEL響應(yīng)頭以開始收集錯誤。
- GET /index.html HTTP/1.1
- NEL: {"report_to": "network-errors", "max_age": 2592000}
ReportingObserver
ReportingObserver 和 Report-To 報頭具有類似但略微不同的用途。
ReportingObserver 是一個 JavaScript API,可以觀察到簡單的客戶端警告,例如棄用和干預(yù)。報表不會自動發(fā)送到服務(wù)器(除非你在回調(diào)中觸發(fā)):
- const observer = new ReportingObserver((reports, observer) => {
- for (const report of reports) {
- // Send report somewhere.
- }
- }, {buffered: true});
- observer.observe();
更敏感的錯誤類型,如CSP違規(guī)和網(wǎng)絡(luò)錯誤不能被 ReportingObserver 觀察到。
Report-To 更加強大,因為它可以捕獲更多類型的錯誤報告(網(wǎng)絡(luò),CSP,瀏覽器崩潰),除了 ReportingObserver 支持的那些。當(dāng)你想要自動向服務(wù)器報告錯誤或捕獲在 JavaScript 中不可能看到的錯誤(網(wǎng)絡(luò)錯誤)時,可以使用它。
總結(jié)
Reporting API 無疑是做端監(jiān)控同學(xué)的福音,它省去了我們很多需要在前端監(jiān)控中需要自己做的工作,未來瀏覽器還會將更多的上報類型應(yīng)用到 Reporting API ,未來將會作為診斷網(wǎng)站問題的重點工具。