我最近一直在Go中缓存http响应,我正试图找出生成正确ETag的最有效方法。
现在我有以下数据可用:
- 渲染模板时要渲染的模板的名称
- 传递到json响应的模板或响应中的动态数据
- 整个响应体
- 身体的长度
- 我可能错过了什么
经过一番思考,我得出的结论是,如果我将模板的名称和正在生成的动态数据结合起来,理论上应该会以最少的开销创建一个合法的唯一ETag,但我不知道如果我开始想要返回大约30kb的html数据库结果,这会有多糟糕。
我使用Go的stdlib中的crc32例程从我传递到它的数据中生成ETag
有没有更好的方法来生成ETag,甚至缓存动态数据?我不能只监视文件的最后一次修改时间,因为数据可以在不更改文件的情况下更改。
通常,您希望使用便宜的东西来计算ETag。原因是,如果客户端发送条件请求(例如通过If-None-Match
HTTP请求标头),则可以决定是否适合发送304 Not Modified
响应,而无需对页面进行所有处理。
例如,如果页面内容有某种修订标识符,那么这可能是一个好的ETag。
如果你需要做所有必要的工作来渲染页面,只是为了生成一个ETag,那么你也可以只使用渲染页面内容的哈希,或者根本不使用ETag。
如果您正在寻找一种高效的ETag机制,并且不需要加密功能强大的东西,我建议使用CRC-32。为了防止冲突,您可以组合一些东西,比如模板名称、数据长度和crc:
func etag(name string, data []byte) string {
crc := crc32.ChecksumIEEE(data)
return fmt.Sprintf(`W/"%s-%d-%08X"`, name, len(data), crc)
}
这将产生类似W/"tpl-17-3074C885"
的etag。