背景

最近在做公司内部的项目,测试在测试过程中发现接口请求完成之后没有带过相关的数据,随后打开控制台查看是否是接口问题,发现接口报如下的异常,状态码是 200,但返回的内容显示不出来,而且控制台是提前打开 Preserve log 的,理论上之前发送的请求是应该会有记录的,但结果确看不到 Response。经过排查过后发现是对 Preserve log 的理解有偏差,由此引发了接下来的探索。

Preserve log 简介

按照 Chrome 官方文档的介绍,Preserve log 如果勾选,在跨页面加载请求时,会保留之前的所有请求,目的是为了方便开发同学排查一些跨站请求是接口的一些问题,比如数据对比等。但是官网没有写的是如果想要看到返回的 Response,你必须在页面跳转之前先提前点击查看该接口,才能在跳转之后看到之前的接口返回的信息,对于那些没有点击过的接口,在下一个页面中是查看不到返回的结果的,Response 看到的信息跟上图是类似的,都会有一个共同的报错“Failed to load response data”。那是不是所有的浏览器都这样呢?还是只是 Chrome 一家是这种情况?接下来对 Preserve log 的兼容性做了一个分析。

Preserve log 兼容性

我们选取三个浏览器做样本,分别是 Chrome、Safari、Firefox。验证的步骤如下:

  1. 选取一个能从 A 网站跳转到 B 网站的页面
  2. 打开控制台,勾选 Preserve log 选项
  3. 刷新页面,找任意一个 A 页面的请求打开,其它的请求不点击
  4. 点击 A 网站 跳转到 B 网站的链接,在 B 网站查看之前 A 网站的请求数据
    实验结果如下:

Chrome

在 Chrome 中,实验结果跟我们之前看到的是一样的,只会对点击的请求做保留,未点击的请求不会展示 Response。

Safari

在 Safari 中,Preserve log 的表现跟 Chrome 是一致的,只有点击之后的接口才会保留 Response,未点击的会展示“尝试载入资源时发生错误”,查看不了相应的结果,Safari 有个好处是,当跳转到 B 网站之后,控制台中 A 网站的请求都置灰了,会方便观察和操作。

Firefox

在 Firefox 中,如果勾选了 Persist Logs 之后,请求是会被完整的保留下来的,在下一个页面中能看到上一个页面完整的请求和返回的信息,说明 Firefox 是不受限制的。

Preserve log 为什么不会完整保留请求日志

通过以上的分析会发现,不同浏览器对保留日志的处理是不一样的。Chrome 这种处理方式在 issue 上也引发了广泛的讨论,而且还是一个历史悠久的 issue,总结下来大致观点分为两派。

反对方:

  • NetWork 出现的错误很容易让别人误以为错误出现在服务端,引起误解
  • 如果重定向发生的非常快,用户是很难去点击链接的,所以还得借助第三方工具帮助
  • Preserve log 有歧义,明明是保留日志,但实际的结果确没有像 Charles 等工具一样完整的保留日志

赞同方(chromium 开发者):

  • 这是“low overhead”的结果,Response 并不会传到 DevTools,除非用户想要查看并点击它,目的是为了避免歪曲测量结果
  • 如果将所有的 Response 都保留在 DevTools,则会增加很多的不必要的内容,如果用户点击了好多的跨站链接,后果不可想象
  • 这是一种折中最好的方案,既兼顾了易用性,也兼顾了灵活性

两方观点各有各的的道理,但我认为,Chrome 应该把这个权限放开给开发者,因为本来 DevTools 就是给开发者用的,Preserve log 并没有解决开发者跨站请求需要查看原链接的诉求,保留日志的本意应该是要保留所有的 Request 和 Response 信息,而不应该做阉割版本,应该由开发者去控制是否开启这一选项,并承担相应的结果。不然有的时候还得通过第三方工具进行抓包或者像 issue 中讲到的那样,需要在代码层面做处理,这无疑让一个本来很简单的功能变得复杂化。

浏览器厂商的改进节奏

issue 中也有一些 Chromium 的反馈,原来认为这个需求没有必要做,而且优先级比较低,17 年的时候因为优先级和资源问题关闭了,但最近看好像又重启了,状态变成了 Open,期待之后的版本能够改善这个问题。

总结

以上是对 Preserve log 做了一个简单的介绍,如果在开发中真的遇到了上面的问题,解决方案可以考虑用以下几种方案:

  1. 使用 Firefox 浏览器(目前貌似用的人比较少)
  2. 如 issue 中所说,通过在代码中打点来进行调试,“window.onunload = function() {debugger;}”,但实际应用起来不太方便
  3. 使用 Charles 等抓包工具进行抓包

参考文档

03-05 22:39