如何在c#中生成http ETag ?

本文关键字:http ETag | 更新日期: 2023-09-27 18:11:02

给定一个文件作为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/

如何在c#中生成http ETag ?

答案是视情况而定。

有两种类型的Etags,弱和强。弱标签允许您执行某些条件操作,但大多数都需要强标签。

对强etag的唯一限制是,如果由于某种原因表示发生了变化,那么etag也会发生变化。如果它是一个文件,您可以生成一个散列,但这迫使您在生成散列时将实体保留在内存中。或者,您可以简单地流式传输内容,并将Etag添加为http标头,但目前几乎没有服务器支持这种(非常有用但不受欢迎的)功能。

tick的分辨率很低,即使内容不同,对同一文件的连续两次写操作也可能具有相同数量的tick。在这个阶段,如果你在浑浊的水中,etag是无效的。和Last-Modified一样的问题。大多数HTTP服务器处理这种情况的方式是根据文件的多个属性,即时间戳,大小和文件对象ID (apache中的inode,可能会在NT上添加对象存储条目的完整路径,IIS也会为该值添加计数器,因此服务器上的两次配置更改将生成不同的etag,以防某些更改)。

如果您使用某种类型的数据库,id +版本应该是一个强etag(再次强调,前提是您拥有的内容不是多个内容的集合,每个内容都可以独立更改,而无需根也更改版本)。

因此,如何计算它实际上取决于您的场景,并且在写入时(在开始服务之前)持久化文件的散列可能会对您最有帮助,特别是因为它是一个非常有用的功能,具有许多其他原因

从语义上讲,ETag应该随着内容的变化而变化:

所以哈希似乎是合适的…但是ETag在不同的url和/或重复文件的不同时间戳上也必须是唯一的…为了安全起见,散列文件,将其与上次修改的时间戳和url连接起来然后散列。

生成与Nginx兼容的静态文件ETag:

// Generate ETag from file's size and last modification time as unix timestamp in seconds from 1970
public static string MakeEtag(long lastMod, long size)
{
    string etag = '"' + lastMod.ToString("x") + '-' + size.ToString("x") + '"';
    return etag;
}
public static void Main(string[] args)
{
    long lastMod = 1578315296;
    long size = 1047;
    string etag = MakeEtag(lastMod, size);
    Console.WriteLine("ETag: " + etag);
    //=> ETag: "5e132e20-417"
}

查看我对不同ETag模式的评论