HTTP 协议请求头 If-Match、If-None-Match 和 ETag

概述

在 HTTP 协议中,请求头 If-MatchIf-None-MatchIf-Modified-SinceIf-Unmodified-SinceIf-Range 主要是为了解决浏览器缓存数据而定义的请求头标准,按照协议规范正确的判断和使用这几个请求头,可以更精准的处理浏览器缓存,从而达到提高系统性能和减少系统带宽的占用的目的。

更精准的处理 Web 缓存效果是可以很明显的:

  • 1、 减少了网络交互,加快页面响应速度,增强用户体验;
  • 2、 减少了网络带宽消耗,因为没有更新的资源就不需要重复返回了,特别是图片、视频、下载文件这类大响应体请求;

当请求中存在上述 If-xxx 时,服务器对附加的条件进行判断,当判定条件为真,才会执行标准的数据处理和数据返回,否则直接返回对应的HTTP错误码。

针对服务端原始资源是否变更目前有两类处理规则:基于修改时间的(If-Modified-SinceIf-Unmodified-Since)和基于自定义标识的(If-MatchIf-None-Match),还有一个是处理文件断电续传使用到的 If-Range

经常做服务端开发的会发现,基于时间的并不能很精准的进行缓存判断,有些场景下后端资源可能在1秒钟以内进行了变更,时间请求头只精确到秒,是不足以覆盖这种场景的。还有一些场景是我们没有定义修改时间的,可能是基于其他标志记录是否被修改的。这种情况下,我们使用 If-MatchIf-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://www.mzph.cn/news/129580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

0基础学编程从哪里入手?零基础学些代码怎么入手

0基础学编程从哪里入手&#xff1f;零基础学些代码怎么入手&#xff1f; 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的软件&#xff0c;向如图…

你的编程能力从什么时候开始突飞猛进?

你的编程能力从什么时候开始突飞猛进&#xff1f; 回顾一下&#xff0c;我的技术能力&#xff08;不仅仅是编程&#xff0c;而是解决问题的能力&#xff09;的进步大约有几个重要的节点: 1. 刚入行时的入门练习题 这个是当年狼厂网页搜索部门的传统&#xff0c;不知道现在还有…

sql server 对称加密例子,很好用

-- 创建对称密钥 CREATE MASTER KEY ENCRYPTION BY PASSWORD 输入一个对称密钥; -- 创建证书 CREATE CERTIFICATE MyCertificate WITH SUBJECT 创建一个证书名称; -- 创建对称密钥的加密密钥 CREATE SYMMETRIC KEY MySymmetricKey WITH ALGORITHM AES_128 ENCRY…

Flink源码解析三之执行计划⽣成

JobManager Leader 选举 首先flink会依据配置获取RecoveryMode,RecoveryMode一共两两种:STANDALONE和ZOOKEEPER。 如果用户配置的是STANDALONE,会直接去配置中获取JobManager的地址如果用户配置的是ZOOKEEPER,flink会首先尝试连接zookeeper,利用zookeeper的leadder选举服务发现…

前端性能分析工具

前段时间在工作中,需要判断模块bundle size缩减对页面的哪些性能产生了影响, 因此需要了解前端的性能指标如何定义的,以及前端有哪些性能分析工具, 于是顺便整理了一篇笔记, 以供前端小白对性能这块知识点做一个入门级的了解. 页面渲染 在了解性能指标和分析工具之前,有必要先…

Minio多节点多驱动分布式部署官网文档翻译

原文链接&#xff1a; Deploy MinIO: Multi-Node Multi-Drive — MinIO Object Storage for Linux The procedures on this page cover deploying MinIO in a Multi-Node Multi-Drive (MNMD) or “Distributed” configuration. MNMD deployments provide enterprise-grade p…

Linux非root用户运行服务实践

前言 以前就知道如果Linux服务以非root的方式运行会增强系统的安全性&#xff0c;但如何去实践呢&#xff1f; Linux安全基础 安全设计原则 最小安全原则 一般应尽可能缩小权限的授予范围 技术手段 用户隔离rwx读写执行权限capability特权权限PAM体系pam_cap模块ACL等 简…

Windows Server 2016使用MBR2GPT.EXE教程!

什么是MBR2GPT.exe&#xff1f; MBR2GPT.exe是微软提供的专业工具&#xff0c;可在命令提示符下运行。使用该工具可以将引导磁盘从MBR转换为GPT分区样式&#xff0c;而无需修改或删除所选磁盘上的任何内容。 在Windows Server 2019和Windows 10&#xff08;1703…

时间序列聚类的直观方法

一、介绍 我们将使用轮廓分数和一些距离度量来执行时间序列聚类实验&#xff0c;同时利用直观的可视化&#xff0c;让我们看看下面的时间序列&#xff1a; 这些可以被视为具有正弦、余弦、方波和锯齿波的四种不同的周期性时间序列 如果我们添加随机噪声和距原点的距离来沿 y 轴…

测试Whisper效果

先去官方上面看看&#xff0c;是否有对应的测试结果 简单找了一下&#xff0c;没找到对应的测试数据 去hugging face 上面找对应的数据集&#xff0c;发现没有现成的数据 找到了几个数据集&#xff0c;但是是收费的 101 Hours – Scene Noise Data by Voice Recorder 1,29…

#stm32整理(一)flash读写

以这篇未开始我将进行stm32学习整理为期一个月左右完成stm32知识学习整理内容顺序没有一定之规写到哪想到哪想到哪写到哪&#xff0c;主要是扫除自己知识上的盲区完成一些基本外设操作。 以stm32f07为例子进行flash读写操作 stm32flash简介 参考资料正点原子和野火开发手册 …

通过akshare获取股票分钟数据

参考:https://blog.csdn.net/qnloft/article/details/131218295 import akshare as ak 个股的 df ak.stock_zh_a_hist_min_em(symbol“000001”, start_date“2023-11-03 09:30:00”, end_date“2023-11-03 15:00:00”, period‘1’, adjust‘’) print(df) date_info df[‘…

6-3 堆排序

description 本题要求实现堆排序中的筛选函数&#xff0c;待排序列的长度1<n<1000。 函数接口定义&#xff1a; void HeapAdjust( HeapType H, int s, int m); 其中L是待排序表&#xff0c;使排序后的数据从小到大排列。 ###类型定义&#xff1a; typedef int KeyType…

自动曝光算法(第二讲)

序言 第一章说了&#xff0c;自动曝光算法的目的&#xff1a;已知当前raw图亮度、当前曝光时间、当前增益和目标亮度&#xff0c;当环境光发生变化的时候&#xff0c;是通过控制增益、曝光时间和光圈使raw图的亮度&#xff0c;保持在目标亮度附近。本章想讲一下目标亮度的相关…

【杂记-遇到的坑】mysql-查询条件不达预期

前言&#xff1a; 业务开发时&#xff0c;遇到的坑&#xff0c;栽进去了&#xff0c;写这个博客&#xff0c;涨点记性 1.连表查询 左连接为例子 A left join B 把A的数据全部取出&#xff0c;能够跟B对应的上&#xff0c;B表的扩展数据也跟着展示出俩 A有B没有的&#xff0c;B的…

路由器基础(九):防火墙基础

防火墙 (Fire Wall) 是网络关联的重要设备&#xff0c;用于控制网络之间的通信。外部网络用户的访问必须先经过安全策略过滤&#xff0c;而内部网络用户对外部网络的访问则无须过滤。现在的防火墙还具有隔离网络、提供代理服务、流量控制等功能。 一、三种防火墙技术 常见的…

hadoop进程启停管理(看这一篇就足够了!)

一、一键启停脚本 Hadoop HDFS组件内置了HDFS集群的一键启停脚本 $HADOP_HOME/sbin/start-all.sh,一键启动HDFS集群 执行原理&#xff1a; 在执行此脚本的机器上&#xff0c;启动SecondaryNameNode 读取core-site.xml内容(fs.defaultFS项)&#xff0c;确认NameNode所在机器&…

【MySQL索引与优化篇】数据库的设计规范

数据库的设计规范 文章目录 数据库的设计规范1. 范式2. 键和相关属性的概念3. 第一范式4. 第二范式5. 第三范式6. 小结7. 反范式化7.1 概述7.2 反范式的新问题7.3 反范式适用场景 8. 巴斯范式9. 第四范式、第五范式和域键范式 1. 范式 在关系型数据库中&#xff0c;关于数据表…

Qt实验室

前言 本系列文章是研究和记录Qt开发过程中遇到的各种问题的集合 由于Qt是一个庞大的开发体系&#xff0c;很难用有限的文案对其做全面深入细致的讲解&#xff0c;因此市面上大多数Qt开发相关的教程都显得极其粗浅入门&#xff0c;通常只能作为最基本的入门教程。但是实际项目…

Ubuntu安装Redis

目录 1. 更新软件包列表2. 安装 Redis3. 启动 Redis4. 验证 Redis 是否启动成功5. 配置 Redis6. 启用 Redis 开机启动7. 验证 Redis 是否可用8. 测试 Redis 在 Ubuntu 20.04 上安装 Redis 非常简单。只需按照以下步骤操作即可&#xff1a; 1. 更新软件包列表 sudo apt update…