Cache-Control, Expires, ETag和If-None-Match

本文介绍了HTTP缓存控制机制,包括Cache-Control、Expires和ETag的使用方法。详细解释了如何通过这些头部信息来减少服务器负载及提高用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Cache-Control

cache-control用于设置缓存. 我们在服务器端设置如下:

response.setHeader('Cache-Control', 'max-age=30')

服务器返回带有cache-control的响应. 当浏览器再次请求同一URL资源时, 若没有超过30秒, 则会加载缓存中的资源. 若超过30秒则会向服务器重新请求.

不能为全部资源设置缓存, 否则当服务器端更新资源时, 客户端用的还是缓存. 通常将首页不设置缓存, 其他资源设置缓存.

不为首页设置cache-control时, 当服务器更新资源时, 资源对应的URL也会改变. 此时客户端发送请求, 其请求资源的URL也会改变. 即客户端不会从缓存中获取资源, 而是从服务器端获取资源.

Expires

expirescache-coontrol的用处一样, 它也是为缓存设置有效时间. 与cache-control不同的是, expires是老的API, cache-control是新的API. 且cache-control的优先级比expires的优先级高.
expires可以用来删除cookie. cookie有下面的特性:

  • 若设置的cookie已存在, 则会覆盖之前设置的cookie.
  • 若设置的cookie不存在, 则会添加到现有cookie

没有删除已存在cookie的直接方法. 间接方法是设置相同的cookie, 并且将cookie的失效时间设置为以前
删除cookie只需设置一个已经过期的时间即可:

response.setHeader('Expires', 'Wed, 21 Oct 1900 07:28:00 GMT')

ETag和If-None-Match

在介绍ETag之前先介绍一下MD5算法. MD5算法是一个摘要算法, 它会为一个文件生成一个数字签名, 这个数字签名是独一无二的.
我们将资源的md5值放在ETag属性中, 这样当我们请求服务器的资源时, 可以比较上次请求的md5值和本次请求的md5值. 注意请求的资源的URL必须是一致的.

  • 若相等则说明资源未更新, 返回部分响应, 包含304状态码, 客户端从缓存中获取资源.
  • 反之说明资源更新了, 服务器返回完整的响应, 即客户端从服务器端获取资源.

ETag在服务器端设置:

let file = md5(string)
response.setHeader('ETag', file)
if (file === request.headers['if-none-match']) {
    response.statusCode = 304//匹配
} else {
    response.write(string)//不匹配
}

当客户端第一次请求资源时, 服务器设置ETag值并返回响应. 若客户端发送第二次请求, 会在请求体中包括If-None-Match字段, 该字段值为上次响应中的ETag值. 服务器接收第二次请求并判断服务器当前资源的ETag值与请求体中的If-None-Match值是否一致. 若一致则返回304状态码, 客户端从缓存中获取资源, 若不一致则返回新的资源.

<think>我们被要求详细解释HTTP头字段If-Modified-SinceIf-None-Match的用途、工作方式以及它们在缓存控制条件请求中的应用场景。 根据用户提供的引用之前的问题,我们知道这两个头字段都属于条件请求头部,用于缓存验证(协商缓存)。 引用[1][2]说明了If-Modified-Since的作用:它基于资源最后修改时间(Last-Modified)进行缓存验证。 引用[3]则概括了整个HTTP缓存机制,包括强缓存(expirescache-control协商缓存(Etag/If-None-MatchLast-Modified/If-Modified-Since)。 下面我们将分别解释这两个头字段,并说明它们如何协同工作。 注意:在回答中,我们将使用中文,并按照要求对数学公式(如果有)使用LaTeX格式,但本题中数学公式较少,重点在解释机制。 另外,我们会在适当的地方引用用户提供的引用内容,并在末尾添加引用标识。 结构: 1. 介绍条件请求协商缓存的背景 2. 分别详细解释If-Modified-SinceIf-None-Match 3. 解释它们的工作流程(结合例子) 4. 讨论应用场景注意事项 5. 总结</think>### HTTP头字段`If-Modified-Since`与`If-None-Match`详解 #### 一、核心作用与定位 这两个请求头字段均属于**条件请求(Conditional Requests)** 机制,用于实现**协商缓存(Validation Caching)**。其核心目标是在客户端已有缓存副本时,向服务器验证资源是否更新: - 若未更新 → 返回 `304 Not Modified` → 客户端直接使用缓存 - 若已更新 → 返回 `200 OK` 新资源 → 更新客户端缓存 ```mermaid graph LR A[客户端发起请求] --> B{携带缓存验证头} B -->|If-Modified-Since<br>或 If-None-Match| C[服务器] C -->|资源未修改| D[返回304] C -->|资源已修改| E[返回200+新资源] ``` #### 二、字段详细解析 ##### 1. `If-Modified-Since` - **作用原理**: 客户端携带**上次响应头中的`Last-Modified`时间值**(资源最后修改时间),服务器比较当前资源修改时间: - 若客户端时间 ≥ 服务器时间 → 返回 `304` - 若客户端时间 < 服务器时间 → 返回 `200` 新资源 - **工作流程**: 1. 首次请求:服务器返回资源及`Last-Modified: Fri, 31 Aug 2007 02:02:20 GMT` 2. 后续请求:客户端自动添加`If-Modified-Since: Fri, 31 Aug 2007 02:02:20 GMT` 3. 服务器校验时间戳决定响应状态[^1][^2] - **典型应用场景**: - 静态资源(如图片/CSS/JS文件)的缓存验证 - 修改频率较低的内容(如新闻文章) ##### 2. `If-None-Match` - **作用原理**: 客户端携带**上次响应头中的`ETag`值**(资源唯一标识符),服务器比较当前资源`ETag`: - 若`ETag`匹配 → 返回 `304` - 若`ETag`不匹配 → 返回 `200` 新资源 - **关键优势**: - 解决时间戳精度问题(如1秒内多次修改) - 处理特殊场景: - 资源内容不变但修改时间变化(如备份恢复) - 分布式服务器时间不同步 - 文件编码改变但内容不变(如gzip重压缩) - **工作流程**: 1. 首次请求:服务器返回`ETag: "45bae1-16a-46d776ac"` 2. 后续请求:客户端添加`If-None-Match: "45bae1-16a-46d776ac"` 3. 服务器校验`ETag`决定响应状态[^3] #### 三、协同工作与优先级 1. **典型协作流程**: ```mermaid sequenceDiagram participant Client participant Server Client->>Server: GET /resource Server-->>Client: 200 OK + Last-Modified + ETag Client->>Server: GET /resource If-Modified-Since: [时间戳] If-None-Match: [ETag] alt 资源未修改 Server-->>Client: 304 Not Modified else 资源已修改 Server-->>Client: 200 OK + 新资源 end ``` 2. **优先级规则**: - 当两者同时存在时,**`If-None-Match`优先级更高**(因`ETag`更精确) - 服务器行为: - 若`ETag`验证通过 → 直接返回`304`(忽略时间戳) - 若`ETag`验证失败 → 再检查`If-Modified-Since` #### 四、应用场景对比 | 场景 | `If-Modified-Since` | `If-None-Match` | |--------------------------|---------------------|-----------------| | 时间戳精度要求高 | ✗ 不适用 | ✓ 适用 | | 资源内容不变时间戳变化 | ✗ 误判失效 | ✓ 准确判断 | | 分布式服务器环境 | ✗ 时间同步问题 | ✓ 稳定适用 | | 简单静态资源缓存 | ✓ 实现简单 | ✓ 更可靠 | | 大文件分块传输 | ✗ 不适用 | ✓ 支持分块验证 | #### 五、最佳实践建议 1. **服务端配置**: - 始终生成`ETag``Last-Modified`响应头 - 对动态内容设置`Cache-Control: no-cache`强制验证 ```nginx # Nginx配置示例 location ~* \.(js|css|png)$ { etag on; add_header Last-Modified ""; } ``` 2. **客户端优化**: - 配合`Cache-Control: max-age=0`实现即时验证 ```http GET /style.css HTTP/1.1 Host: example.com Cache-Control: max-age=0 If-None-Match: "abc123" ``` 3. **性能影响**: - 成功`304`响应可减少90%+带宽(仅传输约150字节头部) - 验证失败时增加约10ms延迟(需完整资源传输) > **关键结论**:现代Web应用应优先采用`ETag/If-None-Match`机制,辅以`Last-Modified/If-Modified-Since`作为降级方案,在保证缓存效率的同时避免"幽灵修改"问题[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值