首页 > 解决方案 > 如何解析通过 Report-To 标头端点报告的 NEL(网络错误日志记录)错误?

问题描述

我正在使用库Network Error Logging添加NEL标头和报告以Report-To在我的 Express.js 服务器上添加标头。

我的代码就像

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 日)

发现一个 W3C 示例正在使用application/reports+json.

另一个 W3C 示例是使用application/report(注意没有s)。

所以我在这里创建了一张在 W3C GitHub 上询问的票。


更新 2(2020 年 10 月 14 日)

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

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

在此处输入图像描述

在此处输入图像描述

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


更新 3(2020 年 10 月 16 日)

这是我最新的代码。我尝试通过使用两个端点进行比较来同时登录报告 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(工作解决方案,2020 年 10 月 28 日)

感谢@IanClelland 的帮助!在我删除 URL 中滥用的内部端口后,它现在可以工作了。也证实了,正如伊恩所说

报告 API 将仅交付到单个端点,以最大限度地减少传出带宽,因此使用多个端点进行冗余的人不会重复计算报告。

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

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"
}

标签: javascriptnode.jsexpressnetwork-error-logging

解决方案


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

很难确切地说现在什么不适合您,但有几点可能会有所帮助:

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

推荐阅读