NancyFX是否支持通过ETag和Last-Modified标头进行静态内容缓存?

bio*_*tal 10 static-content browser-cache nancy

我希望我的静态内容(图像,javascript文件,css文件等)只有在文件更新后才能完整提供.

如果自上次请求的文件并没有改变(如由确定ETagLast-Modified响应报头值),那么我想通过客户端浏览器中使用的文件的缓存版本.

南希是否支持此功能?

bio*_*tal 14

南希确实部分支持ETagLast-Modified标题.它为所有静态文件设置它们,但从版本0.13开始,它对这些值没有任何作用.这是南希代码:

Nancy.Responses.GenericFileResponse.cs

if (IsSafeFilePath(rootPath, fullPath))
{
    Filename = Path.GetFileName(fullPath);

    var fi = new FileInfo(fullPath);
    // TODO - set a standard caching time and/or public?
    Headers["ETag"] = fi.LastWriteTimeUtc.Ticks.ToString("x");
    Headers["Last-Modified"] = fi.LastWriteTimeUtc.ToString("R");
    Contents = GetFileContent(fullPath);
    ContentType = contentType;
    StatusCode = HttpStatusCode.OK;
    return;
}
Run Code Online (Sandbox Code Playgroud)

为了使用的的ETagLast-Modified你需要添加一对夫妇的修改方法扩展标头值.我直接从GitHub中的Nancy源代码中借用了这些内容(因为此功能计划在将来发布),但最初的想法来自Simon Cropp - 与NancyFX的条件响应

扩展方法

public static void CheckForIfNonMatch(this NancyContext context)
{
    var request = context.Request;
    var response = context.Response;

    string responseETag;
    if (!response.Headers.TryGetValue("ETag", out responseETag)) return;
    if (request.Headers.IfNoneMatch.Contains(responseETag))
    {
        context.Response = HttpStatusCode.NotModified;
    }
}

public static void CheckForIfModifiedSince(this NancyContext context)
{
    var request = context.Request;
    var response = context.Response;

    string responseLastModified;
    if (!response.Headers.TryGetValue("Last-Modified", out responseLastModified)) return;
    DateTime lastModified;

    if (!request.Headers.IfModifiedSince.HasValue || !DateTime.TryParseExact(responseLastModified, "R", CultureInfo.InvariantCulture, DateTimeStyles.None, out lastModified)) return;
    if (lastModified <= request.Headers.IfModifiedSince.Value)
    {
        context.Response = HttpStatusCode.NotModified;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,您需要使用AfterRequestNancy BootStrapper中的钩子调用这些方法.

引导程序

public class MyBootstrapper :DefaultNancyBootstrapper
{
    protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
    {
        pipelines.AfterRequest += ctx =>
        {
            ctx.CheckForIfNoneMatch();
            ctx.CheckForIfModifiedSince();
        };
        base.ApplicationStartup(container, pipelines);
    }
    //more stuff
}
Run Code Online (Sandbox Code Playgroud)

通过Fiddler观察响应,您将看到静态文件的第一个命中,使用200 - OK状态代码下载它们.

此后,每个请求返回一个304 - Not Modified状态代码.更新文件后,请求再次使用200 - OK状态代码下载...依此类推.