如何为浏览器report-to/report-uri/report-endpoints Reporting API附加额外信息?
如何为CSP及浏览器报告附加额外信息
一、使用ReportingObserver API添加自定义数据
你可以通过ReportingObserver的回调函数直接修改报告对象,注入额外信息(比如当前用户ID、测验答案等)。以下是具体实现示例:
1. 基础配置示例
// 存储需要附加的自定义数据(比如从登录状态或测验页面获取) const customReportData = { userId: localStorage.getItem('currentUserId'), // 假设用户ID存在localStorage quizAnswers: window.quiz?.currentAnswers || {} // 测验页面的当前答案集合 }; // 创建ReportingObserver实例 const observer = new ReportingObserver((reports, observer) => { // 遍历所有报告,附加自定义数据 reports.forEach(report => { // 添加自定义字段到report.body report.body.customData = { ...customReportData, timestamp: Date.now() // 可选:添加时间戳 }; // 手动发送修改后的报告到服务器(替代浏览器默认发送,或者补充发送) fetch('/your-report-endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(report), credentials: 'include' // 确保携带Cookie }); }); // 如果不需要浏览器默认发送报告,调用observer.disconnect() // observer.disconnect(); }, { types: ['csp-violation', 'crash', 'deprecation'], // 监听需要的报告类型 buffered: true // 捕获页面加载前的缓存报告 }); // 启动监听 observer.observe();
2. 针对测验页面的特殊处理
在测验页面,你可以实时更新customReportData.quizAnswers,比如用户每选一个选项就保存:
// 监听测验选项点击事件 document.querySelectorAll('.quiz-option').forEach(option => { option.addEventListener('change', (e) => { const questionId = e.target.dataset.questionId; customReportData.quizAnswers[questionId] = e.target.value; }); });
二、报告发送时是否携带Cookie?
- 同域报告端点:默认情况下,浏览器发送CSP或ReportingObserver报告时会自动携带当前域名的Cookie。
- 跨域报告端点:需要满足两个条件才会携带Cookie:
- 服务器端响应头设置
Access-Control-Allow-Credentials: true; - 发送请求时指定
credentials: 'include'(如上面的fetch示例),或者在ReportingObserver对应的report-to组配置中设置credentials: true。
- 服务器端响应头设置
三、除服务器端URL附加外的其他方法
除了在报告端点URL中拼接参数(如/report?userId=xxx),还有以下客户端方案:
1. Service Worker拦截并修改报告请求
通过Service Worker拦截浏览器发送的报告POST请求,在请求头或请求体中添加额外信息:
// service-worker.js self.addEventListener('fetch', (event) => { if (event.request.url.includes('/your-report-endpoint')) { event.respondWith( (async () => { // 获取原始请求体 const originalBody = await event.request.json(); // 添加自定义数据 originalBody.customData = { userId: await self.clients.matchAll() .then(clients => clients[0].postMessage({ type: 'GET_USER_ID' })) }; // 创建新请求 const modifiedRequest = new Request(event.request, { body: JSON.stringify(originalBody), headers: event.request.headers }); // 发送修改后的请求 return fetch(modifiedRequest); })() ); } });
2. 自定义错误监听结合手动报告
对于特定场景(如测验页面的错误/崩溃),可以结合window.onerror、window.unhandledrejection或beforeunload事件,手动收集额外信息并发送报告:
// 监听未捕获的JS错误 window.onerror = (message, source, lineno, colno, error) => { const reportData = { type: 'js-error', message, source, lineno, customData: { userId: localStorage.getItem('currentUserId'), quizAnswers: window.quiz?.currentAnswers } }; // 发送自定义报告 fetch('/your-report-endpoint', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(reportData), credentials: 'include' }); };
内容的提问来源于stack exchange,提问作者user802599
相关产品推荐
相关产品推荐

