如何在 C# 中生成 http ETag?
给定一个作为 http 请求的一部分返回的文件。为该文件创建 ETag 的正确方法是什么?
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html# sec14.19
我已经看到它通过多种方式完成
- ,使用文件的最后写入时间转换为刻度。这就是 NancyFX 所做的 https://github.com/NancyFx/Nancy/blob /master/src/Nancy/Responses/GenericFileResponse.cs
- 使用文件的哈希 http://hartzer.wordpress.com/2009/10/04/client-side-caching/< /a>
Given a file being returned as part of a http request. What is the correct method of creating an ETag for that file?
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19
I have seen it done several ways
- Using the last write time of the file converted to ticks. Which is what NancyFX does https://github.com/NancyFx/Nancy/blob/master/src/Nancy/Responses/GenericFileResponse.cs
- Using a hash of the file http://hartzer.wordpress.com/2009/10/04/client-side-caching/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
答案是,这取决于情况。
Etag 有两种:弱 Etag 和强 Etag。弱的允许您执行某些条件操作,但大多数都需要强的 etag。
对强 etag 的唯一限制是,如果表示形式由于某种原因发生变化,etag 也会发生变化。如果它是一个文件,您可以生成一个哈希值,但这会迫使您在生成该文件时将实体保留在内存中。或者,您可以简单地流式传输内容并将 Etag 添加为尾随 http 标头,但目前几乎没有服务器支持该(非常有用且不受欢迎)功能。
刻度的分辨率较低,即使内容不同,同一文件上的两次连续写入也可能具有相同数量的刻度。在那个阶段,如果 etag 很强大并且你陷入了泥水,那么它现在就无效了。与 Last-Modified 确实存在相同的问题。大多数HTTP服务器处理这个问题的方式是根据文件的多个属性(又名时间戳、大小和可能的文件对象ID)为文件提供一个etag(apache中的inode,可能添加NT上对象存储条目的完整路径,以及IIS 也为该值添加了一个计数器,因此服务器上的两次配置更改将生成不同的 etag,以防万一发生变化)。
如果您使用某种数据库,则 id + 版本应该是一个强大的 etag(前提是您拥有的内容不是多个内容的聚合,每个内容都可以独立更改而无需根更改版本)。
因此,如何计算它实际上取决于您的场景,并且在写入时保留文件的哈希值(在开始服务之前)可能会对您有最大帮助,特别是因为出于许多其他原因,它是一个非常有用的功能。
The answer is that it depends.
There are two kinds of Etags, weak and strong ones. The weak ones let you do certain conditional operations, but most of them will require strong etags.
The only restriction on a strong etag is that if the representation changes for whatever reason, so does the etag. If it's a file you can generate a hash, but that forces you to keep the entity in-memory while you generate that. Alternatively, you could simply stream the content and add the Etag as a trailing http header, but nearly no server currently supports that (very useful and unloved) piece of functionality.
Ticks have a low resolution, and it is possible that two contiguous writes on the same file will have the same number of ticks, even though the content is different. At that stage, the etag is now invalid if it was strong and you're in muddy water. Same issue as with Last-Modified really. The way most HTTP servers deal with that is to give a file an etag based on multiple of its properties, aka timestamp, size and probably file object ID (inode in apache, probably adding the full path to the object store entry on NT, and IIS adds a counter to that value too so two config changes on a server would generate different etags, in case something changes).
If you use some sort of database, the id + version ought to be a strong etag (provided, again, that the content you ahve is not an aggregate of multiple things that each may change independently without the root changing versions too).
So how to calculate it really depends on your scenario, and persisting a hash of the file on write (before starting serving) will probably help you the most, especially as it's a very useful feature to have for many other reasons.
从语义上讲,当内容发生变化时,ETag 应该发生变化:
所以哈希似乎是合适的...但是 ETag 在不同的 URL 和/或重复文件的不同时间戳上也必须是唯一的...所以为了安全起见,对文件进行哈希处理,将其与上次修改的时间戳以及 url 和哈希值再次连接起来......
Semantically the ETag should change when the content changes:
So the Hash seems appropriate... but the ETag must also be unique on different URLs and/or different timestamps of duplicate files... so to be on the safe side hash the file, concatenate that with the timestamp of the last modification and the url and hash that again...
要生成与 Nginx 兼容的静态文件的 ETag:
请参阅 我的评论 关于不同的 ETag 模式
To generate a static file's ETag which will be compatible with Nginx:
See my comment about different ETag schemas