这个坑值得记一笔。CDN 按 Accept 头自动返回 WebP,源站响应里没有 Vary: Accept,中间缓存把 WebP 版本缓存给了不支持的客户端,蜘蛛抓图时收到的是 HTML 错误页。
刚开始盯着「图片 404 时兜底返回了 HTML,Content-Type 仍是 text/html」,折腾了半个多小时,排掉了。
排查方向其实有限,先把可能性排一排。同一 URL 按 Accept 返回不同内容却没有声明 Vary;CDN 缓存键里没带 Accept,先到的版本覆盖全部;图片搜索抓取要求响应体是真实图像数据。
第一件事是分别用带 Accept 和不带的请求对比响应
curl -sI -H 'Accept: image/webp' https://www.example.com/img/1024.jpg | grep -iE 'content-type|vary'
再往下在图片响应上补 Vary 头
add_header Vary Accept;
接着把 CDN 缓存键加上 Accept 维度
curl -sI https://www.example.com/img/1024.jpg | grep -i 'x-cache'
剩下的就是确认图片 404 时不再返回 HTML
curl -s https://www.example.com/img/not-exist.jpg | head -c 60
别只看报错消失,验证要多做一步。带与不带 Accept 的请求都返回 image 类型且 Vary 头存在,图片搜索的抓取错误里不再出现内容类型不符。
补一句。内容协商的页面必须在缓存层声明 Vary,否则缓存会替所有客户端做决定,图片和接口都吃过这个亏。报错文案容易误导,真正的原因往往在相邻那一层的日志里。
