内容没变时服务器只回一个状态码,条件请求靠哪个标识判断

📅 2026-10-12 👁️ 0

内容没变的时候服务器可以只回一个状态码,条件请求靠哪个标识判断,答案是资源自带的那一枚版本标识。浏览器初次拿到资源时,响应头里会附带一个 ETag,即标识某一版资源的响应头;等本地缓存到期,浏览器并不急着重新下载整份内容,而是发起条件请求,用 If-None-Match 这个请求头把上次拿到的旧值带回去。服务器把带回的值和当前版本的值比对,一致就返回 304,响应里没有任何正文,只告诉客户端:你手上那一版仍然可用。

缓存过期就等于重新下载整份内容吗

缓存的工作节奏分两段。新鲜期内资源直接读本地副本,连请求都不必发;过期之后资源也没有立刻作废,而是先问服务器一句:这一版还作数吗。这一问就是条件请求。没有版本标识,过期就只能重新下载全部内容,哪怕一个字都没改,整份文本或图片被反复搬运显然是浪费;有了标识,判断就降级为比对两个字符串,命中一致时连正文都不必发送。

这枚标识代表什么

标识的规则只有一条:同一地址上的资源内容发生变化,就必须生成新的标识值;内容不变,值就保持不变。它不描述内容长什么样,也不编码内容有多长,只回答一个问题:现在这一版,还是你上次那一版吗。

它与按最后修改时间判断的方式是两套各自独立的校验。时间方式比的是文件上次被动过是什么时候,版本方式比的是这是不是同一版内容。时间粒度较粗,同一秒内的多次改动可能分辨不出;文件被重新保存而内容未变时,时间戳更新还会造成误判。版本标识对内容变化的判断更直接,两者可以共存,客户端带哪个条件头,服务器就按对应的那套逻辑来判。

回访时怎么做比对

流程串起来是这样:服务器在响应里给出标识值,客户端连同内容一起存下;缓存过期后客户端发出新请求,并在 If-None-Match 里附上旧值;服务器计算当前版本的标识再比对。一致就返回 304,客户端继续使用本地副本;不一致就返回 200 和完整新内容,附带新值,客户端替换旧缓存。

生成标识的关键,是把内容真的变了和只是重新渲染了一遍区分开。如果输入里掺了每次请求都波动的成分,比如渲染时刻、随机数,每次响应都会算出新值,比对永远失败,校验就退化成每次都全量下载,等于没有缓存。内容以数据库渲染为主的站点更容易踩到这一点:正文存在库里,配套资源本身稳定,标识更应只取决于真正代表内容的输入。集群各节点的计算输入也要一致,否则同一版内容算出不同值,校验会莫名落空。

强校验与弱校验有什么差别

标识值前面出现 W/ 前缀,表示这是弱校验标识;没有前缀则是强校验标识。弱标识易于生成,但不适合逐字节比较:两边相等只能说明内容在语义层面大致相当,不能保证每个字节都相同。

更实际的影响在分段请求上。浏览器有时用 Range 头只请求文件的一段:弱标识会让这类范围请求无法命中缓存,强标识下范围请求仍可缓存。因为范围请求要求拿到的那一段与整份文件严格对应,弱标识既然不承诺逐字节一致,这段内容是否还是原来那段就无从确认。依赖分段拉取的资源场景,更适合使用强标识。

内容频繁改动的站点怎么用

文章改一次就是一版,标识跟着换值,回访者自然会拿到新内容。需要斟酌的是易变部分:页面里若嵌了实时统计、个性化问候这类每次都在变的内容,整页标识就会每次都变,回访校验全部落空。常见的处理是把易变部分拆出去单独请求,让主体内容保持稳定版本,标识才有恒定的可能。对静态资源,标识照常生成,新鲜期放长一些,过期后的校验大多能命中 304。此外要留意,服务器或框架大版本升级可能改变标识的计算方式,让旧值一夜之间全部对不上,宜按预期内的发布影响来安排。

常见问题

问:这套标识和按修改时间判断要同时配吗? 答:两套是各自独立的校验方式,可以共存。带标识旧值就按版本比对,带时间条件就按时间比对,两者互补而非替代。

问:收到不带正文的 304 是不是请求失败了? 答:不是。304 是校验成功的正常结果,含义是缓存里那一版仍然可用,客户端随即使用本地副本。没有正文,恰恰是省下重复传输的表现。

问:为什么我们的站点从来见不到不带正文的响应? 答:通常是标识每次都在变。检查生成输入里是否混入了渲染时刻之类的波动,以及集群各节点的计算方式是否一致。输入稳定后,内容未变的回访才会命中。

问:改了内容但客户端迟迟没拿到新版,和这套机制有关吗? 答:有可能。内容变了却没有生成新的标识值,回访比对仍会一致,客户端会继续使用旧缓存。同一地址的资源内容发生变化时必须换值,这一步不能省。

相关文章

浏览器会标出请求来自本站还是外站,服务端怎么据此挡住跨站请求

浏览器会给请求加上标明来源关系的几个 Sec-Fetch 请求头,前端脚本改不了它们。取值区分同源、同站、跨站与无发起方,服务端按这些关系决定放行还是拒绝,就能对跨站请求伪造做出一道与写操作确认互补的防线;这组头只在可信地址的请求里发送。本文讲四个取值的含义、按上下文放行的写法,以及它与回合级操作审批各自管什么。

2026-10-12

用户退出登录后浏览器里还留着旧数据,响应头怎么要求清除

退出登录时浏览器里留着的缓存和本地存储不会自动消失。Clear-Site-Data 响应头是给客户端的清除信号,可按项清缓存、凭据、存储与执行上下文,且只在加密连接里生效:凭据清到整个注册域,存储只清当前来源。站内登录态由 JWT 承载,客户端这一层本地数据要靠它配合收尾,公共设备上尤其值得加。

2026-10-12

页面里嵌第三方视频,iframe 的能力授权按什么放行

页面里嵌第三方视频涉及两层限制:来源域名按白名单放行,摄像头、定位、自动播放这些能力按最小集逐项授权。PbootCMS 在 V3.2.18 的更新记录里对可信视频域名保留默认来源策略,并对 allow 属性做了 token 白名单。本文解释内嵌框架为什么同时带着脚本与媒体能力、精确域与子域通配怎么分,以及放行与授权为什么要分开配。

2026-10-12

网站挂在代理后面,登录锁定和黑名单为什么会认错来源地址

网站挂在反向代理后面时,程序读到的连接来源往往是代理地址,而转发头里的内容又由客户端可控,把两层混为一谈会让登录锁定和黑名单认错对象。PbootCMS 在 V3.2.25 的更新记录里修过无条件信任来源转发头的问题。本文讲两层地址各自的来历、只在可信链路里取最右可信值的做法,以及限速与锁定该用哪一层。

2026-10-12

连接还没握完就收到请求,服务器为什么宁可返回一个过早状态码

TLS 的早期数据让客户端在第一个往返里就把请求发出去,省下一次握手等待,代价是这类请求存在被重放的风险。425 Too Early 表示服务器不愿冒险处理一个可能被重放的请求,宁可先拒。本文讲早期数据省的是什么、风险落在哪一类请求上、幂等与非幂等为什么要分开对待,以及以 Go 语言为技术栈的服务在这一层要做什么取舍。

2026-10-12

自己的图片被别的网站直接引用时,靠哪个响应头决定放不放行

自己的图片被别的网站直接引用时,决定放不放行的是资源方而不是引用方。Cross-Origin-Resource-Policy 响应头由被引用的资源设置,声明哪些来源可以加载它,取值分同源、同站、跨来源三档,默认挡住的是不带 cors 的跨站请求。本文讲三档各放行到哪一层、它与发起方的隔离头不是同一端,以及图片、字体各自要不要放开。

2026-10-12

服务器默认把程序版本写进响应头和错误页,要不要收掉这层指纹

多数 Web 服务器默认把程序版本写进 Server 响应头和错误页,Nginx 的 server_tokens 指令默认就是 on,关到 off 之后两处都不再带版本信息。收掉这层指纹能减少按版本撞库的便利,但它只是减少信息暴露,不构成防线。本文讲版本号从哪两处漏出去、关掉后还剩什么,以及宝塔、Docker 等不同部署方式各要在哪一层改。

2026-10-12

调整页面排版会不会更容易被生成式引擎引用,实验给出两个百分比

有一项生成式引擎优化研究把内容结构拆成文档架构、信息分块与视觉强调三层,在六个主流生成式引擎上做实验,报告被引用率提升 17.3%、主观质量提升 18.5%,且不改主题内容。本文解释这两个百分比各自指什么、结构提升为什么不等于内容质量提升,以及它和站内自动生成 llms.txt 这类站点说明的分工。

2026-10-12