跨域请求服务端返回的 304 状态码会被浏览器修改成 200,是浏览器的 BUG 吗 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
请不要在回答技术问题时复制粘贴 AI 生成的内容
jiangzm

跨域请求服务端返回的 304 状态码会被浏览器修改成 200,是浏览器的 BUG 吗

  •  
  •   jiangzm Aug 3, 2023 3093 views
    This topic created in 998 days ago, the information mentioned may be changed or developed.

    这个问题仅出现在 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 ?

    15 replies    2023-08-03 23:06:03 +08:00
    jiangzm
        1
    jiangzm  
    OP
       Aug 3, 2023
    很早之前就有个感觉 CDN 资源在浏览器中很少显示 304 状态,应该也是和这个问题有关。
    sujin190
        2
    sujin190  
       Aug 3, 2023 via Android
    304 不是未修改可以用缓存。然后浏览器就读缓存成功了,最后给你返回 200 没问题啊,毕竟已经有正确的内容了,是你理解的有问题吧
    TirionHo
        3
    TirionHo  
       Aug 3, 2023
    本来就拿不到 304 ,304 拿到的就是 200 ,网上一堆教程判断 304 的 demo 都是坑
    deplivesb
        4
    deplivesb  
       Aug 3, 2023
    https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304

    304 表示服务端不需要再次发送资源到客户端,包含隐式重定向。此时 chrome 发现本地存在该资源,自然就 200 啊
    wonderfulcxm
        5
    wonderfulcxm  
       Aug 3, 2023
    @sujin190 那么同域请求怎么会显示 304 了?
    jiangzm
        6
    jiangzm  
    OP
       Aug 3, 2023
    @sujin190 #2 原始报文不应该被修改,如果是强缓存直接从本地拿的显示 200 没问题,已经发起了远程请求应该直接显示响应的状态码才对

    @hepeng10 #3 304 就是 HTTP 标准定义的怎么可能拿不到 304 , 是不是有点孤陋寡闻了

    @deplivesb #4 这个就要看 chromium 怎么定义的这个 200 ,304 确实要读本地缓存,是不是读了缓存(强缓存和协商缓存)统一都是 200 ,就忽略协商缓存过程响应的 304

    @wonderfulcxm #5 从来没见过 304 状态吗
    jiangzm
        7
    jiangzm  
    OP
       Aug 3, 2023
    1 、同跨正常显示 304


    2 、跨域显示 200 、服务端响应是 304


    3 、Safrai 跨域请求显示 304
    jiangzm
        8
    jiangzm  
    OP
       Aug 3, 2023
    4 、Safrai 跨域请求显示 304 (报文)
    jiangzm
        9
    jiangzm  
    OP
       Aug 3, 2023
    如果 chromium 真的是把读了缓存(强缓存和协商缓存)就显示 200 状态, 那同域请求 304 应该也显示 200 才对而不是同域正常显示 304 跨域就改成 200 。 所以应该不是这个规则的原因。 @deplivesb
    jiangzm
        11
    jiangzm  
    OP
       Aug 3, 2023
    TirionHo
        12
    TirionHo  
       Aug 3, 2023
    你这么确定能拿到 304 ,我还想看看什么情况下代码中拿到的状态码是 304 ,拿到了 @我一下,谢谢。
    我之前就遇到过这个问题,我是没搞出拿到 304 的情况
    jiangzm
        13
    jiangzm  
    OP
       Aug 3, 2023
    @hepeng10 #12 http 客户端( ajax/fetch )确实拿到的是 200 ,即使网络面板显示的是 304 。 应该是自动读取了本地缓存,有了响应内容状态就变了。
    shansing
        14
    shansing  
       Aug 3, 2023
    没细看,如果真是同域保持 304 跨域转成 200 ,盲猜隐私方面的原因,防止网站猜测用户历史记录、生成指纹之类,跟之前取消超链接 :visited 样式类似。
    TirionHo
        15
    TirionHo  
       Aug 3, 2023
    又问了下 ChatGPT ,这是它的回答:

    如果开发者工具中显示的是响应状态码为 304 ,但是在 Ajax 请求的代码中打印出来的是 200 ,这可能是因为浏览器的缓存机制导致的。

    当浏览器进行 Ajax 请求时,如果之前已经请求过同一个资源,并且服务器返回了 304 状态码,表示资源未修改,那么浏览器会直接从缓存中获取该资源,并返回 200 状态码。这样做是为了减少网络流量和加快页面加载速度。

    实际上,浏览器在处理条件请求(返回 304 )时,对开发者是透明的,这意味着在 Ajax 请求的代码中,你无法直接获取到 304 状态码。浏览器会自动处理缓存,并将从缓存中获取资源后返回 200 状态码。
    About     Help     Advertise     Blog     API     FAQ     Solana     2541 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 49ms UTC 16:06 PVG 00:06 LAX 09:06 JFK 12:06
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86