Express与浏览器缓存头及304响应码行为:为何304显示为200?
问题描述
为了理解缓存头与响应码的行为机制,我编写了两个Express接口进行实验:
第一个接口 /users-a
模拟3000ms数据库查询延迟,返回public, max-age=10的缓存头:
app.get("/users-a", async (req, res) => { await new Promise((res) => setTimeout(res, 3000)); res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Cache-Control", `public, max-age=10`); res.json(users); });
实验现象:
- 首次请求耗时3000ms,返回完整响应
- 10秒内重复请求直接使用浏览器磁盘缓存,耗时极短
- 响应自动带有Express生成的Etag头:
后续验证请求会携带Etag: W/"1a-Q1ZzAew6rLbf4JEZbVarkQiSXKo"If-None-Match头:If-None-Match: W/"1a-Q1ZzAew6rLbf4JEZbVarkQiSXKo"
第二个接口 /users-b
模拟浏览器持有过期数据时收到304响应的场景:
app.get("/users-b", async (req, res) => { res.setHeader("Access-Control-Allow-Origin", "*"); const ifNoneMatch = req.headers["if-none-match"]; if (ifNoneMatch && etags.has(ifNoneMatch)) { res.sendStatus(304); } else { await new Promise((res) => setTimeout(res, 3000)); res.setHeader("Cache-Control", `public, max-age=${10}`); res.json(users); const etagValue = res.getHeader("etag"); etags.add(etagValue); } });
实验现象:
- Express代码确实执行了
res.sendStatus(304)逻辑,但浏览器网络面板却显示200响应及响应体,且请求耗时极短。
疑问:这是否是浏览器对304响应码的默认行为——将其转为200显示?
解答
是的,这就是浏览器的默认处理逻辑。
当服务器返回304 Not Modified时,浏览器会自动将该响应映射为200 OK,并展示本地缓存中保存的响应体。这么做的核心目的是简化前端开发:不管是直接读取缓存(显示200 (from cache)),还是通过服务器验证缓存有效后复用(实际收到304但显示200),前端代码拿到的都是一致的状态码和完整响应体,无需额外处理304的特殊场景。
如果想确认服务器真实返回的状态码,可以通过两种方式验证:
- 在浏览器网络面板的「响应头」或「详情」区域,能看到服务器实际返回的
304 Not Modified状态 - 使用
curl命令直接请求接口,会直接看到服务器返回的304状态和响应头
内容的提问来源于stack exchange,提问作者dwjohnston
相关产品推荐
相关产品推荐

