如何解析通过 Report-To header 端点报告的 NEL(网络错误记录)错误?

How to parse NEL (Network Error Logging) errors reported through Report-To header endpoint?

我正在使用库 Network Error Logging to add NEL header and report-to 在我的 Express.js 服务器上添加 Report-To header。

我的代码是这样的

app.use(reportTo({
  groups: [
    {
      group: 'default',
      max_age: 31536000,
      include_subdomains: true,
      endpoints: [
        {
          url: myReportToURL,
          priority: 1,
        },
      ],
    },
  ],
}));
app.use(NEL({
  report_to: 'default',
  max_age: 31536000,
  include_subdomains: true,
}));

有关它们的更多信息,请访问

我以前使用 https://report-uri.com 来收集 NEL 错误,效果很好。

它收集了不同类型的 NEL 错误,如屏幕截图所示:

但是,现在我想构建自己的错误解析器,然后进行收集。

我从 CSP 错误解析器中得到了见解,根据 我可以通过

解析
bodyParser.json({ type: 'application/json' });
bodyParser.json({ type: 'application/csp-report' });

对于 NEL,我发现了这个 https://w3c.github.io/reporting/#media-type-registration

那么我应该这样解析吗?

bodyParser.json({ type: 'application/reports+json' });

或者是什么意思?

bodyParser.json({ type: 'application/json' });
bodyParser.json({ type: 'application/reports' });

如果有人知道如何在本地触发 NEL 错误,那对测试也很有帮助。谢谢!


更新 1(2020 年 10 月 14 日)

发现 one W3C example 正在使用 application/reports+json

Another W3C example 正在使用 application/report(注意没有 s)。

所以我在 here 的 W3C GitHub 创建了一个请求单。


更新 2(2020 年 10 月 14 日)

我已请求 fix W3C 文档问题。正确的格式是 application/reports+json.

关于如何在本地触发 NEL 错误。 Express.js NEL 和 Report-To 库作者 James (@Cherry) 在 GitHub 上 here 得到了一个建议。所以我尝试连接 https://fakedomainabccba.com 以获得 dns.name_not_resolved 或类似的 DNS 错误。

但是,Chrome 88.0.4291.0 并没有发送 NEL 错误,也没有显示在网络选项卡中。


更新 3(2020 年 10 月 16 日)

这是我最新的代码。我尝试通过使用两个端点进行比较来登录到 Report URI 和我自己的服务器。报告 URI 确实收到了新报告,但是,我的服务器仍然有问题。

(网站和 API 域相同,所以我不应该有 CORS 问题。如果它被 CORS 阻止,我可以在日志中看到它。)

app.use(reportTo({
  groups: [
    {
      group: 'default',
      max_age: 31536000,
      include_subdomains: true,
      endpoints: [
        {
          url: 'https://xxx.report-uri.com/xxx', // Report URI still works
          priority: 1,
        },
        {
          url: 'https://www.example.com/api/report-to', // "example" is my domain currently still has issue
          priority: 1,
        },
      ],
    },
  ],
}));
app.use(NEL({
  report_to: 'default',
  max_age: 31536000,
  include_subdomains: true,
}));

router.post('/api/report-to', bodyParser.json({ type: 'application/reports+json' }), (req, res) => {
  console.log('reportTo', req.body);
  res.sendStatus(200);
});

更新 4(工作解决方案,10/28/2020)

感谢@IanClelland 的帮助!在我删除 URL 中误用的内部端口后,它现在可以工作了。也证实了,正如 Ian 提到的

The Reporting API will only deliver to a single endpoint, to minimize outgoing bandwidth, and so that people who use multiple endpoints for redundancy don't double-count reports.

所以最终的工作版本看起来像

app.use(reportTo({
  groups: [
    {
      group: 'default',
      max_age: 31536000,
      include_subdomains: true,
      endpoints: [
        {
          url: 'https://www.example.com/api/report-to',
          priority: 1,
        },
      ],
    },
  ],
}));
app.use(NEL({
  report_to: 'default',
  max_age: 31536000,
  include_subdomains: true,
}));

router.post('/api/report-to', bodyParser.json({ type: 'application/reports+json' }), (req, res) => {
  console.log('reportTo', req.body);
  res.sendStatus(200);
});

我收到的成功日志看起来像

{
  "age":42187,
  "body":{
    "elapsed_time":674,
    "method":"GET",
    "phase":"application",
    "protocol":"h2",
    "referrer":"",
    "sampling_fraction":1,
    "server_ip":"2606:4700:3032::681b:b258",
    "status_code":404,
    "type":"http.error"
  },
  "type":"network-error",
  "url":"https://www.example.com/undefined",
  "user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4305.0 Safari/537.36"
}

如果您 https://report-uri.com 工作了,那么您可能已经完成了大部分工作。

现在很难准确地说出什么对您不起作用,但有几点可能会有所帮助:

  • application/reports+json 是正确的内容类型;解释器不正确。 (谢谢,我会解决的。)
  • 触发报告的站点和报告端点都需要使用 HTTPS; Chrome 将从其缓存中删除任何不安全的端点。
  • 如果报告端点与您的站点位于不同的来源,则它将需要支持 CORS:您需要处理 CORS 预检请求以允许请求继续。
  • 您不会在 Devtools 网络选项卡中看到报告; Chrome 在浏览器进程中将它们单独排队,然后在任何特定浏览器选项卡之外发送它们。它们通常会在一分钟内发送,但如果发送失败,Chrome 会重试几次然后放弃。从chrome://net-export/导出网络日志,然后在https://netlog-viewer.appspot.com/
  • 查看,就可以看到网络交换