页面加载完成,文字正常显示,只有一张图变成了破碎的图标。第一反应是怪隧道,因为隧道正是那个变了的东西。在那之前,先弄清楚浏览器究竟为这张图请求了哪个 URL,因为页面 URL 和图片 URL 是两份不同的证据。大多数图片丢失的报告最终都落在一个从未收到可用请求的主机上,而这个答案只需看一眼网络面板。

三个条件决定该往哪里看

第一个条件是图片是否与页面来自同一台主机。单独的图片主机需要自己的域名解析、自己的连接和自己的 TLS 身份,所以页面能加载并不能说明它的情况。

第二个条件是浏览器是否在发出请求之前就把它拦下了。混合内容、内容安全策略和 referrer 规则都能让一张图被拦下而不产生普通的服务器响应,因此列表里根本看不到失败的请求。

第三个条件是投递成功而渲染失败,也就是字节到了、图却仍然不显示。这三个条件对应三个不同的负责人,只有第一个才是网络问题。

What you seeWhere the fault sits
Request absent from the listMarkup, lazy loading or a policy that blocked it
Request failed or timed outResolution, route, TLS or the image host itself
Request returned 200, image blankResponse type, decoding or rendering

找出浏览器实际选中的资源

你在页面源码里看到的 URL,往往不是被请求的那个 URL。源集、picture 元素和 CSS 背景都会让浏览器根据视口宽度、像素密度或格式支持选择另一个资源。懒加载的图片在页面进入某个状态之前可能根本不会被请求。

把元素和请求放在一起看,报告问题时保留发起者信息。图片元素参考(MDN)在一处讲清了源选择、加载行为和 referrer 控制,足以判断是哪个属性选中了出错的 URL。

记录主机名、状态码、任何重定向链以及响应的内容类型。返回登录页的 200 不是一个可用的图片,而重定向到 HTML 错误页在读到类型之前看起来和损坏的文件一模一样。

先读状态,再看网络

超时、请求被拒和解码错误需要不同的后续步骤,而区分它们的是状态码。超时指向解析、路由或不应答的主机。请求被拒指向策略或授权层。解码错误指向字节或格式。

如果请求根本没有出现,就不要再盯着网络,而要看标记。最常见的原因是源集里有一条浏览器优先选中、但服务器上已不存在的记录,其次是一个脚本从未让它可见的元素。

仅凭这一区分,就能避免这类报告里的大部分无用功。

浏览器拦截时,没有响应可读

混合内容是典型情况:HTTPS 页面通过明文 HTTP 请求一张图,请求被拦下而不是失败,控制台会记录原因。内容安全策略会产生同样的形态,消息里会点名被拦下的指令。剥离 referrer 的策略也可能让防外链的主机返回占位图而不是原图。

在动网络路径之前先读已记录的原因,因为路由改变并不会让这类拦截变好。增加跨源权限也不是解法:显示另一台主机的图片和在 canvas 里读取它的像素是两回事,只有后者才需要人们常粘贴的那些响应头。

对于你管理的网站,在资源所有者那边修正资源 URL、响应或策略,并保持授权与 referrer 的要求不变。对于你无法控制的网站,把页面和请求证据发给它的支持渠道,而不是转载私有或会过期的资源链接。

在不改变证据的前提下比较路径

如果你确实想测试访问路径,就把其他一切固定住:同一个页面、同一个账号、同一张选中的图片,只改一条被允许的路径。比较请求条目而不是渲染结果,因为渲染结果只说明图有没有出现,不说明为什么。

在新路径上加载成功,并不能证明该路径已获授权;图片一直坏着,也不能证明是隧道的错。如果图片已被删除或访问被有意限制,请使用受支持的替代方案,而不是关闭证书校验或复制他人的受保护素材。

工作顺序:确定选中的 URL,读取它的状态和类型,检查是否有已记录的拦截原因,然后一次只比较一处路径改动。

相关文章