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