From b56da336c07c54bae028c694f4e9a33523eea7da Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 28 Jun 2013 12:19:40 -0700 Subject: [PATCH] Added cache headers to static resources. --- ...questExtensions.cs => ReqResExtensions.cs} | 20 +++++++ NzbDrone.Api/Frontend/IndexModule.cs | 52 +++++++++++++++++-- NzbDrone.Api/Frontend/StaticResourceMapper.cs | 1 - .../Frontend/StaticResourceProvider.cs | 6 ++- NzbDrone.Api/NzbDrone.Api.csproj | 2 +- 5 files changed, 73 insertions(+), 8 deletions(-) rename NzbDrone.Api/Extensions/{RequestExtensions.cs => ReqResExtensions.cs} (58%) diff --git a/NzbDrone.Api/Extensions/RequestExtensions.cs b/NzbDrone.Api/Extensions/ReqResExtensions.cs similarity index 58% rename from NzbDrone.Api/Extensions/RequestExtensions.cs rename to NzbDrone.Api/Extensions/ReqResExtensions.cs index 17e3292b0..8139b469b 100644 --- a/NzbDrone.Api/Extensions/RequestExtensions.cs +++ b/NzbDrone.Api/Extensions/ReqResExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using Nancy; using Nancy.Responses; @@ -33,5 +34,24 @@ namespace NzbDrone.Api.Extensions { return new JsonResponse(model, NancySerializer) { StatusCode = statusCode }; } + + public static IDictionary DisableCache(this IDictionary headers) + { + headers.Add("Cache-Control", "no-cache, no-store, must-revalidate"); + headers.Add("Pragma", "no-cache"); + headers.Add("Expires", "0"); + + return headers; + } + + public static IDictionary EnableCache(this IDictionary headers) + { + headers.Add("Cache-Control", "max-age=31536000 , public"); + headers.Add("Expires", "Sat, 29 Jun 2020 00:00:00 GMT"); + headers.Add("Last-Modified", "Sat, 29 Jun 2000 00:00:00 GMT"); + headers.Add("Age", "193266"); + + return headers; + } } } \ No newline at end of file diff --git a/NzbDrone.Api/Frontend/IndexModule.cs b/NzbDrone.Api/Frontend/IndexModule.cs index ffcbcdf17..2ae21ff4d 100644 --- a/NzbDrone.Api/Frontend/IndexModule.cs +++ b/NzbDrone.Api/Frontend/IndexModule.cs @@ -1,22 +1,37 @@ using System; +using System.IO; using Nancy; -using Nancy.Security; +using Nancy.Responses; +using NzbDrone.Common; +using NzbDrone.Common.Cache; +using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Api.Extensions; namespace NzbDrone.Api.Frontend { public class IndexModule : NancyModule { - public IndexModule() + private readonly IDiskProvider _diskProvider; + private readonly ICached _indexCache; + + private readonly string _indexPath; + + public IndexModule(IDiskProvider diskProvider, ICacheManger cacheManger, IAppDirectoryInfo appDirectory) { + _diskProvider = diskProvider; + + _indexPath = Path.Combine(appDirectory.StartUpPath, "UI", "index.html"); + + _indexCache = cacheManger.GetCache(typeof(IndexModule)); //Serve anything that doesn't have an extension Get[@"/(.*)"] = x => Index(); } private object Index() { - if( + if ( Request.Path.Contains(".") - || Request.Path.StartsWith("/static", StringComparison.CurrentCultureIgnoreCase) + || Request.Path.StartsWith("/static", StringComparison.CurrentCultureIgnoreCase) || Request.Path.StartsWith("/api", StringComparison.CurrentCultureIgnoreCase) || Request.Path.StartsWith("/signalr", StringComparison.CurrentCultureIgnoreCase)) { @@ -24,7 +39,34 @@ namespace NzbDrone.Api.Frontend } - return View["UI/index.html"]; + var htmlResponse = new HtmlResponse(); + + htmlResponse.Contents = stream => + { + var lastWrite = _diskProvider.GetLastFileWrite(_indexPath); + var text = _indexCache.Get(lastWrite.Ticks.ToString(), GetIndexText); + + var streamWriter = new StreamWriter(stream); + + streamWriter.Write(text); + streamWriter.Flush(); + }; + + + htmlResponse.Headers.DisableCache(); + + return htmlResponse; + } + + + private string GetIndexText() + { + var text = _diskProvider.ReadAllText(_indexPath); + + text = text.Replace(".css", ".css?v=" + BuildInfo.Version); + text = text.Replace(".js", ".js?v=" + BuildInfo.Version); + + return text; } } } \ No newline at end of file diff --git a/NzbDrone.Api/Frontend/StaticResourceMapper.cs b/NzbDrone.Api/Frontend/StaticResourceMapper.cs index dac512688..c178fe696 100644 --- a/NzbDrone.Api/Frontend/StaticResourceMapper.cs +++ b/NzbDrone.Api/Frontend/StaticResourceMapper.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; -using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; namespace NzbDrone.Api.Frontend diff --git a/NzbDrone.Api/Frontend/StaticResourceProvider.cs b/NzbDrone.Api/Frontend/StaticResourceProvider.cs index 66bbaaedf..b7664f819 100644 --- a/NzbDrone.Api/Frontend/StaticResourceProvider.cs +++ b/NzbDrone.Api/Frontend/StaticResourceProvider.cs @@ -5,6 +5,7 @@ using NLog; using Nancy; using Nancy.Responses; using NzbDrone.Common; +using NzbDrone.Api.Extensions; namespace NzbDrone.Api.Frontend { @@ -43,7 +44,10 @@ namespace NzbDrone.Api.Frontend if (_diskProvider.FileExists(filePath)) { - return new StreamResponse(() => File.OpenRead(filePath), MimeTypes.GetMimeType(filePath)); + var response = new StreamResponse(() => File.OpenRead(filePath), MimeTypes.GetMimeType(filePath)); + response.Headers.EnableCache(); + + return response; } _logger.Warn("File {0} not found", filePath); diff --git a/NzbDrone.Api/NzbDrone.Api.csproj b/NzbDrone.Api/NzbDrone.Api.csproj index 3510c293c..7dd87b51a 100644 --- a/NzbDrone.Api/NzbDrone.Api.csproj +++ b/NzbDrone.Api/NzbDrone.Api.csproj @@ -156,7 +156,7 @@ - +