
这个问题仅出现在 Chrome 和 Edge , 也给 chromium 官方提了 Bug 不知道会不会确认是个 BUG 。
1.server code
const express = require('express'); const cors = require('cors'); const app = express(); const port = 3000; app.use(cors({ origin: '*', allowedHeaders: ['If-None-Match', 'If-Modified-Since'], exposedHeaders: ['ETag', 'Last-Modified', 'Cache-Control'], maxAge: 86400, })); app.get('/getcache', (req, res) => { if (req.header('If-None-Match')) { return res.status(304).end(); } const time = Date.now(); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('ETag', time); res.send(JSON.stringify({ time })) }); app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); }); 2.client code
fetch('http://localhost:3000/getcache'); 在其他网页(跨域)的控制台执行上面 fetch 请求即可,第二次请求后内容没变化但是状态码一直是 200 。用代理软件抓包发现服务端实际响应的是 304 ,在 Safrai 或者 Postman 中请求也是 304 。
如果不是跨域请求,在同域请求 Chrome 是能正常显示 304 状态。
不明白 chrome 会修改这个状态,实际不管是同域还是跨域都支持了协商缓存,状态码为啥要修改成 200 ?
1 jiangzm OP 很早之前就有个感觉 CDN 资源在浏览器中很少显示 304 状态,应该也是和这个问题有关。 |
2 sujin190 Aug 3, 2023 via Android 304 不是未修改可以用缓存。然后浏览器就读缓存成功了,最后给你返回 200 没问题啊,毕竟已经有正确的内容了,是你理解的有问题吧 |
3 TirionHo Aug 3, 2023 本来就拿不到 304 ,304 拿到的就是 200 ,网上一堆教程判断 304 的 demo 都是坑 |
4 deplivesb Aug 3, 2023 https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304 304 表示服务端不需要再次发送资源到客户端,包含隐式重定向。此时 chrome 发现本地存在该资源,自然就 200 啊 |
5 wonderfulcxm Aug 3, 2023 @sujin190 那么同域请求怎么会显示 304 了? |
6 jiangzm OP @sujin190 #2 原始报文不应该被修改,如果是强缓存直接从本地拿的显示 200 没问题,已经发起了远程请求应该直接显示响应的状态码才对 @hepeng10 #3 304 就是 HTTP 标准定义的怎么可能拿不到 304 , 是不是有点孤陋寡闻了 @deplivesb #4 这个就要看 chromium 怎么定义的这个 200 ,304 确实要读本地缓存,是不是读了缓存(强缓存和协商缓存)统一都是 200 ,就忽略协商缓存过程响应的 304 @wonderfulcxm #5 从来没见过 304 状态吗 |
![]() | 7 jiangzm OP |
8 jiangzm OP |
9 jiangzm OP 如果 chromium 真的是把读了缓存(强缓存和协商缓存)就显示 200 状态, 那同域请求 304 应该也显示 200 才对而不是同域正常显示 304 跨域就改成 200 。 所以应该不是这个规则的原因。 @deplivesb |
11 jiangzm OP @victimsss #10 这个问题应该很早就有,看之前别人提的 issue 有的状态都 fixed ,不知道为啥最新版还是有这个问题 bug list: https://bugs.chromium.org/p/chromium/issues/list?q=304%20status%20code&can=1 bug fixed: https://bugs.chromium.org/p/chromium/issues/detail?id=1351286&q=304%20status%20code&can=1 stackoverflow: https://stackoverflow.com/questions/61584984/chrome-shows-200-ok-status-in-network-even-if-server-returns-304 |
12 TirionHo Aug 3, 2023 你这么确定能拿到 304 ,我还想看看什么情况下代码中拿到的状态码是 304 ,拿到了 @我一下,谢谢。 我之前就遇到过这个问题,我是没搞出拿到 304 的情况 |
13 jiangzm OP @hepeng10 #12 http 客户端( ajax/fetch )确实拿到的是 200 ,即使网络面板显示的是 304 。 应该是自动读取了本地缓存,有了响应内容状态就变了。 |
14 shansing Aug 3, 2023 没细看,如果真是同域保持 304 跨域转成 200 ,盲猜隐私方面的原因,防止网站猜测用户历史记录、生成指纹之类,跟之前取消超链接 :visited 样式类似。 |
15 TirionHo Aug 3, 2023 又问了下 ChatGPT ,这是它的回答: 如果开发者工具中显示的是响应状态码为 304 ,但是在 Ajax 请求的代码中打印出来的是 200 ,这可能是因为浏览器的缓存机制导致的。 当浏览器进行 Ajax 请求时,如果之前已经请求过同一个资源,并且服务器返回了 304 状态码,表示资源未修改,那么浏览器会直接从缓存中获取该资源,并返回 200 状态码。这样做是为了减少网络流量和加快页面加载速度。 实际上,浏览器在处理条件请求(返回 304 )时,对开发者是透明的,这意味着在 Ajax 请求的代码中,你无法直接获取到 304 状态码。浏览器会自动处理缓存,并将从缓存中获取资源后返回 200 状态码。 |