HTTP 协议请求头 If-Match、If-None-Match 和 ETag
概述
在 HTTP 协议中,请求头 If-Match、If-None-Match、If-Modified-Since、If-Unmodified-Since、If-Range 主要是为了解决浏览器缓存数据而定义的请求头标准,按照协议规范正确的判断和使用这几个请求头,可以更精准的处理浏览器缓存,从而达到提高系统性能和减少系统带宽的占用的目的。
更精准的处理 Web 缓存效果是可以很明显的:
- 1、 减少了网络交互,加快页面响应速度,增强用户体验;
- 2、 减少了网络带宽消耗,因为没有更新的资源就不需要重复返回了,特别是图片、视频、下载文件这类大响应体请求;
当请求中存在上述 If-xxx 时,服务器对附加的条件进行判断,当判定条件为真,才会执行标准的数据处理和数据返回,否则直接返回对应的HTTP错误码。
针对服务端原始资源是否变更目前有两类处理规则:基于修改时间的(If-Modified-Since、If-Unmodified-Since)和基于自定义标识的(If-Match、If-None-Match),还有一个是处理文件断电续传使用到的 If-Range。
经常做服务端开发的会发现,基于时间的并不能很精准的进行缓存判断,有些场景下后端资源可能在1秒钟以内进行了变更,时间请求头只精确到秒,是不足以覆盖这种场景的。还有一些场景是我们没有定义修改时间的,可能是基于其他标志记录是否被修改的。这种情况下,我们使用 If-Match、If-None-Match 来进行资源是否变更的更精准判断,这两个头基于一个自定义字符串传送,这个字符串你可以自己定义,例如用 md5,时间戳都可以,需要注意它俩需要结合 ETag 请求头一起使用(ETag 指代一个独一无二的版本号字符串,称为“实体标签”)。
下文针对 If-Match、If-None-Match 和 ETag 的交互原理及使用方法进行说明。
详解
服务端对资源记录一个 ETag(实体标记)的字段,当资源更新后ETag也会随之更新。
所以当客户端 If-Match 的值若与服务端的ETag一致,才会执行请求,否则拒绝处理返回412状态码。
交互图:


示例代码:
package com.example.webfluxreactivedemo1.controller;import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** HTTP请求头IfMatch和ETag处理** @author 单红宇* @date 2023/11/2 10:09*/@RestController
@RequestMapping
public class IfMatchController {/*** 获取资源接口** @param id 资源ID* @param clientETag 请求头中的 If-None-Match* @return ResponseEntity*/@GetMapping("/resource/{id}")public ResponseEntity<String> getResource(@PathVariable String id,@RequestHeader("If-None-Match") String clientETag) {// 检查资源是否存在以及资源最新的ETag是否与请求头中的If-None-Match匹配boolean resourceExists = checkResourceExists(id);boolean etagMatch = checkETagMatch(id, clientETag);if (!resourceExists) {// 如果资源不存在,返回404 Not Foundreturn ResponseEntity.status(HttpStatus.NOT_FOUND).build();} else if (!etagMatch) {// 如果资源存在且ETag不匹配(即资源已经发生了变更),则返回资源内容return ResponseEntity.ok().header(HttpHeaders.ETAG, this.generateETag(id)).body("Resource content");} else {// 如果资源存在且ETag匹配(即资源没有发生变更),返回304和空响应体return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build();}}/*** 修改文章内容** @param id 文章ID* @param clientETag 请求头中的 If-Match* @return ResponseEntity*/@GetMapping("/updateArticle/{id}")public ResponseEntity<String> updateArticle(@PathVariable String id,@RequestHeader("If-Match") String clientETag) {// 检查资源是否存在以及资源最新的ETag是否与请求头中的If-Match匹配boolean etagMatch = checkETagMatch(id, clientETag);if (etagMatch) {// 如果资源存在且ETag匹配,即文章没有被其他人修改过,执行更新操作String newETag = "返回文章最新的ETag";// articleService.update(id);return ResponseEntity.ok().header(HttpHeaders.ETAG, newETag).body("修改成功");} else {// 如果ETag不匹配,说明文章被其他人修改过,用户需要获取最新内容后再基于最新内容修改提交,防止多人同时修改文章内容出现覆盖问题// 返回412 Precondition Failedreturn ResponseEntity.status(HttpStatus.PRECONDITION_FAILED).build();}}// 如果资源存在但ETag不匹配,返回412 Precondition Failed/*** 检查资源是否存在** @param id 资源ID* @return true=存在*/private boolean checkResourceExists(String id) {// 在这里实现检查资源是否存在的逻辑return true;}/*** 检查资源ETag是否匹配,即判定资源的ETag是否发生了变动** @param id 资源ID* @param clientETag 浏览器客户端传过来的ETag* @return 当资源已经被更新时返回false,资源未更新返回true*/private boolean checkETagMatch(String id, String clientETag) {// 在这里实现检查资源ETag是否与请求头中的If-Match/If-None-Match匹配的逻辑return true;}/*** 生成一个ETag** @param resourceId 资源ID* @return ETag*/public String generateETag(String resourceId) {// 在这里实现检查资源是否存在的逻辑String eTag = "根据resourceId按照自己的逻辑生成etag,比如你可以使用md5";// 注意ETag必须使用双引号包起来返回,这是HTTP协议规范要求return "\"" + eTag + "\"";}
}
常见误区
以下是关于这两个字段的一些常见误区:
-
错误的使用方式:有些开发者可能会错误地将If-None-Match和If-Match混淆或颠倒使用。例如,本应使用If-None-Match来检查缓存有效性的情况下使用了If-Match,这可能导致不必要的请求失败。
-
不了解Etag的工作机制:Etag是一个与特定资源关联的确定值,通常由服务器生成并存储。当资源发生变化时,Etag也会相应地更新。而有些开发者可能误认为Etag是由客户端生成和管理的,这可能导致无法正确使用If-Match或If-None-Match。
-
不正确的Etag格式:Etag的格式应该是ASCII字符串,可能包含一个
"W/"前缀来表示弱比较算法。有些开发者可能会忽略这一点,导致Etag格式不正确,从而影响缓存控制的效果。
为了避免这些错误,建议开发者仔细阅读HTTP规范,确保正确理解和使用If-Match和If-None-Match字段。同时,也需要了解和掌握Etag的工作机制和正确的使用方法。
(END)
相关文章:
HTTP 协议请求头 If-Match、If-None-Match 和 ETag
概述 在 HTTP 协议中,请求头 If-Match、If-None-Match、If-Modified-Since、If-Unmodified-Since、If-Range 主要是为了解决浏览器缓存数据而定义的请求头标准,按照协议规范正确的判断和使用这几个请求头,可以更精准的处理浏览器缓存&#x…...
DAY42 1049.最后一块石头的重量II + 494.目标和 + 474.一和零
1049.最后一块石头的重量II 题目要求:有一堆石头,每块石头的重量都是正整数。 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x < y。那么粉碎的可能结果如下: …...
uniapp原生插件之安卓华为统一扫码HMS Scan Kit
插件介绍 华为统一扫码服务(Scan Kit)提供便捷的条形码和二维码扫描、解析、生成能力 插件地址 安卓华为统一扫码HMS Scan Kit - DCloud 插件市场 超级福利 uniapp 插件购买超级福利 详细使用文档 详细使用文档 插件申请权限 android.permi…...
数模国赛——多波束测线问题模型建立研究分析
第一次参加数模国赛,太菜了~~~~意难平 问题一 画出与测线方向垂直的平面和海底坡面的交线构成一条与水平面夹角为𝐀的斜线的情况下的示意图进行分析,将覆盖宽度分为左覆盖宽度和右覆盖宽度,求出它们与海水深度和𝐀、…...
[AUTOSAR][诊断管理][ECU][$37] 请求退出传输。终止数据传输的(上传/下载)
文章目录 一、简介二、服务请求报文定义肯定响应支持的NRC三、示例流程Step 1:Step 2:报文示例:Step 1:请求RequestDownload(0x34)服务Step 2:请求TransferData (0x36)服务,传输数据Step 3:请求RequestTransferExit(0x37)服务总结:三、示例代码37_req_transfer_e…...
vue+canvas实现横跨整个页面的动态的波浪线(贝塞尔曲线)
本来写这个特效 我打算用css实现的,结果是一波三折,我太难了,最终没能用css实现,转战了canvas来实现。来吧先看效果图 当然这个图的波浪高度、频率、位置、速度都是可调的,请根据自己的需求调整,如果你讲波浪什么的调大一下 还有有摆动的效果哦。 以下是完整代码 <…...
LeetCode算法题解| 669. 修剪二叉搜索树、108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树
一、LeetCode 669. 修剪二叉搜索树 题目链接:669. 修剪二叉搜索树 题目描述: 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变…...
直播界很火的无线领夹麦克风快充方案 Type-C接口 PD快充+无线麦克风可同时进行
当前市场上流行一款很火的直播神器,无线领夹麦克风(MIC),应用于网红直播,网课教学,采访录音,视频录制,视频会议等等场景。 麦克风对我们来说并不陌生,而且品类有很多。随…...
Jmeter 汉化中文语言
找到 bin -> jmeter.propertise 修改参数:languageen --> languagazh_CN OK!...
centos9 stream 下 rabbitmq高可用集群搭建及使用
RabbitMQ是一种常用的消息队列系统,可以快速搭建一个高可用的集群环境,以提高系统的弹性和可靠性。下面是搭建RabbitMQ集群的步骤: 基于centos9 stream系统 1. 安装Erlang和RabbitMQ 首先需要在所有节点上安装Erlang和RabbitMQ。建议使用官…...
代码随想录算法训练营第10天|232. 用栈实现队列 225. 用队列实现栈
JAVA代码编写 232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): 实现 MyQueue 类: void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除…...
线上Kafka集群如何调整消息存储时间
这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党 Kafka版本 kafka_2.13-3.5.0 背景 Kafka 默认消息存储时间为7天,实际线上的业务使用Kafka更多的是一些数据统计之类的业务,大多是朝生夕…...
[迁移学习]DA-DETR基于信息融合的自适应检测模型
原文标题为:DA-DETR: Domain Adaptive Detection Transformer with Information Fusion;发表于CVPR2023 一、概述 本文所描述的模型基于DETR,DETR网络是一种基于Transformer的目标检测网络,详细原理可以参见往期文章:…...
【MATLAB】全网唯一的13种信号分解+FFT傅里叶频谱变换联合算法全家桶
有意向获取代码,请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有13种信号分解FFT傅里叶频谱变换联合算法,绝对不亏,知识付费是现今时代的趋势,而且都是我精心制作的教程,有问题可随时反馈~也可单独获取某一…...
Nginx安装与配置
1.下载安装包 官网下载地址:nginx: download 可以先将安装包下载到本地再传到服务器,或者直接用wget命令将安装包下载到服务器,这里我们直接将安装包下载到服务器上。未安装wget命令的需要先安装wget,yum install -y wget [root…...
linux笔记总结-基本命令
参考: 1.Linux 和Windows比 比较 (了解) 1. 记住一句经典的话:在 Linux 世界里,一切皆文件 2. Linux目录结构 /lib • 系统开机所需要最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几 乎所有…...
[PHP]禅道项目管理软件ZenTaoPMS源码包 v16.4
禅道项目管理软件ZenTaoPMS一键安装包是一款国产的开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体,是一款专业的研发项目管理软件,完整地覆盖了项目管理的核心流程。注重实效的管理思想,合理的软件…...
Required String parameter ‘name‘ is not present
[org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter name is not present] 服务端有参数name,客户端没有传上来...
路由器基础(五): OSPF原理与配置
开放式最短路径优先 (Open Shortest Path First,OSPF) 是一个内部网关协议 (Interior Gateway Protocol,IGP),用于在单一自治系统(Autonomous System,AS) 内决策路由。OSPF 适合小型、中型、较大规模网络。OSPF 采用Dijkstra的最短路径优先算法 (Shortest Pat…...
Leetcode1128. 等价多米诺骨牌对的数量
Every day a Leetcode 题目来源:1128. 等价多米诺骨牌对的数量 解法1:暴力 代码: class Solution { public:int numEquivDominoPairs(vector<vector<int>> &dominoes){int n dominoes.size(), count 0;for (int i 0;…...
前端工程化:Vite与Rollup构建优化
前端工程化:Vite与Rollup构建优化 大家好,我是欧阳瑞(Rich Own)。今天想和大家聊聊前端工程化这个重要话题。作为一个全栈开发者,构建工具是日常开发中不可或缺的一部分。今天就来分享一下Vite和Rollup的构建优化技巧…...
7B秒杀70B!大模型微调秘籍全解:从理论到实战,玩转高效适配!
本文系统介绍了大模型微调的理论框架与实践流程。阐述了微调的必要性,即弥补通用大模型在领域知识、输出格式及行为对齐上的不足,并说明微调效果可超越更大参数的未微调模型。文章深入解析了微调原理,对比了全参数微调与高效微调(…...
Stream Deck与Arduino打造物联网信息看板:软硬云结合实战
1. 项目概述:打造你的专属物理信息看板如果你和我一样,是个桌面极客或者直播爱好者,那你对Elgato的Stream Deck一定不陌生。这个小玩意儿最初是为直播设计的,可以一键切换场景、播放音效,堪称效率神器。但它的潜力远不…...
【免费下载】 MATLAB从入门到精通教程 - PDF文档下载指南【matlab下载】
MATLAB从入门到精通教程 - PDF文档下载指南 欢迎来到《MATLAB从入门到精通教程》的资源页面!本资源旨在为所有想要深入学习MATLAB编程语言的学者和工程师提供一份详尽、全面的学习资料。这份权威的PDF文档是英文版,非常适合希望掌握MATLAB核心功能及高级…...
【亲测免费】 电机速度闭环控制(代码详细注释)
电机速度闭环控制(代码详细注释) 【下载地址】电机速度闭环控制代码详细注释 本仓库提供了电机速度闭环控制的实践教程,特别适合对电机控制、尤其是PID控制算法感兴趣的学习者。PID控制是一种广泛应用于工程领域的闭环控制策略,能…...
MATLAB仿真GPS调制和捕获
一,中频数据捕获: 当捕获通道状态空闲时,启动中频数据存储,此时根据当前要捕获的卫星的来选择射频通道,并将相应的载波频率和码频率写入寄存器中,使能存储操作;当一次捕获运算完成之后,需要重新存储中频数据。 卫星选择:初始化时,将所有卫星设置为待捕获状态,用一…...
为什么龙华选了3DGS?详解高斯泼溅、倾斜摄影、点云在治理场景中的优劣
一、行业核心技术科普:三种主流三维建模技术的原理与定位在城市治理与数字孪生领域,倾斜摄影、点云和3D高斯泼溅(3DGS)是三种主流的三维建模技术,它们各有侧重,互为补充。倾斜摄影:大范围实景的…...
3步搞定Unity游戏中文翻译:XUnity.AutoTranslator完全指南
3步搞定Unity游戏中文翻译:XUnity.AutoTranslator完全指南 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为外语游戏的语言障碍而苦恼吗?想体验原汁原味的游戏内容却看不懂菜…...
机器人抓取技能自动化:从仿真学习到现实迁移的实践指南
1. 项目概述与核心价值最近在机器人抓取领域,一个名为simpliolabs/manus-open-claw-skill-hunter-and-developer的项目引起了我的注意。乍一看这个标题,它像是一个开源工具或框架,核心围绕着“机械手开放爪具”的“技能猎人”与“开发者”。这…...
探索DeepMosaics:当AI遇见图像隐私保护与修复的艺术
探索DeepMosaics:当AI遇见图像隐私保护与修复的艺术 【免费下载链接】DeepMosaics Automatically remove the mosaics in images and videos, or add mosaics to them. 项目地址: https://gitcode.com/gh_mirrors/de/DeepMosaics 在数字内容创作与分享日益普…...
