本文深入探讨了 http etag 与 3xx 重定向的交互机制,阐明了 etag 在重定向场景下的关联规则和条件请求的优先级。通过 go 语言客户端 etag 管理实践,分析了在自动重定向过程中 etag 存储的潜在问题,并基于 rfc 规范提出了优化策略,强调将 etag 与最终响应的 url 正确关联,以确保缓存验证的准确性。
HTTP ETag(实体标签)是 Web 服务器响应头中的一个标识符,用于标识特定资源版本。它通常是资源的某
个内容的哈希值或其他唯一标识。当客户端再次请求同一资源时,可以通过在请求头中携带 If-None-Match 字段(值为上次收到的 ETag),向服务器发起条件请求。如果服务器发现资源的 ETag 未发生变化,则返回 304 Not Modified 状态码,指示客户端使用本地缓存副本,从而节省带宽和服务器处理能力。
为了在 Go 语言中实现自定义的 ETag 缓存管理,我们可以扩展 net/http.Client,在发送请求前检查本地缓存的 ETag,并在收到响应后更新 ETag。以下是一个基本的实现示例:
package util
import (
"net/http"
"net/url"
)
// HttpClient 结构体扩展了 http.Client,并增加了 ETag 存储功能
type HttpClient struct {
http.Client
// etags 映射存储 URL 到其对应的 ETag
etags map[url.URL]string
}
// Do 方法重写了 http.Client 的 Do 方法,以实现 ETag 逻辑
func (hc *HttpClient) Do(req *http.Request) (*http.Response, error) {
const ETAG_SERVER_HEADER = "ETag" // 服务器返回的 ETag 头
const ETAG_CLIENT_HEADER = "If-None-Match" // 客户端发送的条件请求头
// 仅对 GET 请求应用 ETag 逻辑
if req.Method != "GET" {
return hc.Client.Do(req)
}
// 检查当前请求 URL 是否有存储的 ETag
etag, ok := hc.etags[*req.URL]
if ok { // 如果存在 ETag,则将其添加到 If-None-Match 请求头中
if req.Header == nil {
req.Header = http.Header{}
}
req.Header.Add(ETAG_CLIENT_HEADER, etag)
}
// 执行实际的 HTTP 请求
response, err := hc.Client.Do(req)
// 如果请求成功且响应有效
if err == nil {
if hc.etags == nil {
hc.etags = make(map[url.URL]string)
}
// 从响应头中获取 ETag,如果存在则存储
serverEtag := response.Header.Get(ETAG_SERVER_HEADER)
if len(serverEtag) != 0 {
// 初始实现:将 ETag 与原始请求 URL 关联
// hc.etags[*req.URL] = serverEtag
// 优化后:将 ETag 与最终响应的 URL 关联
hc.etags[*response.Request.URL] = serverEtag
}
}
return response, err
}上述代码展示了一个自定义的 HttpClient,它在发送 GET 请求时会尝试带上 If-None-Match 头,并在收到 200 OK 响应时存储服务器返回的 ETag。然而,当涉及到 HTTP 重定向(如 302 Found)时,ETag 的关联性和条件请求的处理会变得复杂。
在理解 ETag 如何与重定向协同工作时,需要关注两个核心问题:ETag 的关联性以及条件请求的优先级。
ETag 始终与其“当前请求的选定表示”(selected representation)相关联。这意味着,如果一个 302 Found 响应包含了 ETag 头,那么这个 ETag 是与 302 响应体中通常包含的“简短超文本说明”相关的,而不是与 Location 头指向的最终资源相关。
例如,当你请求 http://foo.com/bar.html,服务器返回 302 Found 并重定向到 http://foo.com/qux.html。如果这个 302 响应本身包含一个 ETag,那么这个 ETag 标识的是 302 响应体(通常是一段提示用户被重定向的文本),而不是 qux.html 的内容。因此,在客户端管理 ETag 时,将 302 响应中的 ETag 与原始请求 URL 关联是没有实际意义的。
HTTP 规范(RFC 7232 第 5 节)明确规定了条件请求(如 If-None-Match)在重定向场景下的处理优先级:
服务器必须忽略所有收到的条件请求,如果其在没有这些条件的情况下对相同请求的响应状态码不是 2xx (成功) 或 412 (先决条件失败)。换句话说,重定向和失败的响应优先于条件请求的评估。
这意味着,即使客户端在请求 http://foo.com/bar.html 时带上了 If-None-Match 头,如果服务器决定通过 302 重定向该请求,它会忽略 If-None-Match 头。服务器不会因为 If-None-Match 匹配而返回 304 Not Modified,而是直接执行重定向。因此,在重定向响应中包含 ETag 虽然技术上可行,但其作为后续条件请求依据的实用性非常有限。
基于上述规范,我们的 Go 语言客户端在处理 ETag 存储时需要进行优化。net/http 客户端在默认情况下会自动处理 3xx 重定向。这意味着,当 hc.Client.Do(req) 返回响应时,如果发生了重定向,response 对象将是重定向链条中 最终 资源的响应。
因此,在我们的 Do 方法中,当存储服务器返回的 ETag 时,不应使用原始请求的 URL (*req.URL) 作为键,而应该使用响应对象中指示的最终请求 URL (*response.Request.URL)。response.Request.URL 字段存储的是导致该 response 产生的实际请求的 URL,它已经包含了 net/http 客户端自动处理重定向后的最终目标 URL。
优化后的 ETag 存储逻辑:
// ... (之前的代码保持不变)
// 执行实际的 HTTP 请求
response, err := hc.Client.Do(req)
// 如果请求成功且响应有效
if err == nil {
if hc.etags == nil {
hc.etags = make(map[url.URL]string)
}
// 从响应头中获取 ETag,如果存在则存储
serverEtag := response.Header.Get(ETAG_SERVER_HEADER)
if len(serverEtag) != 0 {
// 关键优化:将 ETag 与最终响应的 URL 关联
// response.Request.URL 是经过所有重定向后,最终获取资源的 URL
hc.etags[*response.Request.URL] = serverEtag
}
}
return response, err
}通过这一修改,我们确保了 ETag 总是与它实际代表的资源(即最终响应的资源)正确关联,避免了因重定向导致的 ETag 混乱或无效。
遵循这些原则,可以确保在复杂的网络交互(包括重定向)中,ETag 机制能够被正确利用,从而有效管理客户端缓存,提升应用性能。
# html
# go
# 状态码
# if
# 标识符
# 对象
# location
# http
# 重定向
# 客户端
# 自定义
# 的是
# 这意味着
# 而不是
# 并在
# 最终目标
# 是一个
# 情况下
相关文章:
5种Android数据存储方式汇总
专业网站制作服务公司,有哪些网站可以免费发布招聘信息?
如何快速完成中国万网建站详细流程?
如何在阿里云部署织梦网站?
建站之星2.7模板快速切换与批量管理功能操作指南
如何访问已购建站主机并解决登录问题?
义乌企业网站制作公司,请问义乌比较好的批发小商品的网站是什么?
简易网站制作视频教程,使用记事本编写一个简单的网页html文件?
建站之星后台管理系统如何操作?
东莞专业制作网站的公司,东莞大学生网的网址是什么?
建站主机选购指南:核心配置优化与品牌推荐方案
如何在Golang中处理模块冲突_解决依赖版本不兼容问题
上海网站制作开发公司,上海买房比较好的网站有哪些?
公司网站制作价格怎么算,公司办个官网需要多少钱?
七夕网站制作视频,七夕大促活动怎么报名?
建站之星安装提示数据库无法连接如何解决?
中山网站制作网页,中山新生登记系统登记流程?
学校建站服务器如何选型才能满足性能需求?
c# await 一个已经完成的Task会发生什么
郑州企业网站制作公司,郑州招聘网站有哪些?
如何用PHP快速搭建高效网站?分步指南
电商平台网站制作流程,电商网站如何制作?
公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?
Swift中swift中的switch 语句
内网网站制作软件,内网的网站如何发布到外网?
网站制作费用多少钱,一个网站的运营,需要哪些费用?
建站主机SSH密钥生成步骤及常见问题解答?
建站之星如何保障用户数据免受黑客入侵?
广平建站公司哪家专业可靠?如何选择?
网站制作需要会哪些技术,建立一个网站要花费多少?
建站主机服务器选型指南与性能优化方案解析
Python lxml的etree和ElementTree有什么区别
无锡营销型网站制作公司,无锡网选车牌流程?
整人网站在线制作软件,整蛊网站退不出去必须要打我是白痴才能出去?
网站建设设计制作营销公司南阳,如何策划设计和建设网站?
宝塔面板如何快速创建新站点?
香港服务器租用每月最低只需15元?
怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?
如何选择网络建站服务器?高效建站必看指南
保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?
建站之星后台管理:高效配置与模板优化提升用户体验
免费公司网站制作软件,如何申请免费主页空间做自己的网站?
香港服务器如何优化才能显著提升网站加载速度?
广东专业制作网站有哪些,广东省能源集团有限公司官网?
如何选择服务器才能高效搭建专属网站?
如何在阿里云高效完成企业建站全流程?
如何在阿里云域名上完成建站全流程?
建站之星代理平台如何选择最佳方案?
如何通过远程VPS快速搭建个人网站?
高端企业智能建站程序:SEO优化与响应式模板定制开发
*请认真填写需求信息,我们会在24小时内与您取得联系。