added cache pipelines

This commit is contained in:
kay.one 2013-08-19 22:53:18 -07:00
parent 4183fecaca
commit 290e072f2e
10 changed files with 122 additions and 37 deletions

View File

@ -1,16 +0,0 @@
using Nancy;
namespace NzbDrone.Api.Extensions
{
public static class CacheHeaderPipeline
{
public static void Handle(NancyContext context)
{
if (context.Response.ContentType.Contains("json"))
{
context.Response.Headers.DisableCache();
}
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using Nancy;
using Nancy.Bootstrapper;
using NzbDrone.Api.Frontend;
namespace NzbDrone.Api.Extensions.Pipelines
{
public class CacheHeaderPipeline : IRegisterNancyPipeline
{
private readonly ICacheableSpecification _cacheableSpecification;
public CacheHeaderPipeline(ICacheableSpecification cacheableSpecification)
{
_cacheableSpecification = cacheableSpecification;
}
public void Register(IPipelines pipelines)
{
pipelines.AfterRequest.AddItemToStartOfPipeline(Handle);
}
private void Handle(NancyContext context)
{
if (_cacheableSpecification.IsCacheable(context))
{
context.Response.Headers.EnableCache();
}
else
{
context.Response.Headers.DisableCache();
}
}
}
}

View File

@ -2,17 +2,18 @@
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using Nancy; using Nancy;
using Nancy.Bootstrapper;
namespace NzbDrone.Api.Extensions namespace NzbDrone.Api.Extensions.Pipelines
{ {
public static class GzipCompressionPipeline public class GzipCompressionPipeline : IRegisterNancyPipeline
{ {
public static void Handle(NancyContext context) public void Register(IPipelines pipelines)
{ {
context.Response.CompressResponse(context.Request); pipelines.AfterRequest.AddItemToEndOfPipeline(c => CompressResponse(c.Request, c.Response));
} }
public static Response CompressResponse(this Response response, Request request) private Response CompressResponse(Request request, Response response)
{ {
if (!response.ContentType.Contains("image") if (!response.ContentType.Contains("image")
&& request.Headers.AcceptEncoding.Any(x => x.Contains("gzip")) && request.Headers.AcceptEncoding.Any(x => x.Contains("gzip"))

View File

@ -0,0 +1,9 @@
using Nancy.Bootstrapper;
namespace NzbDrone.Api.Extensions.Pipelines
{
public interface IRegisterNancyPipeline
{
void Register(IPipelines pipelines);
}
}

View File

@ -0,0 +1,33 @@
using Nancy;
using Nancy.Bootstrapper;
using NzbDrone.Api.Frontend;
namespace NzbDrone.Api.Extensions.Pipelines
{
public class IfModifiedPipeline : IRegisterNancyPipeline
{
private readonly ICacheableSpecification _cacheableSpecification;
public IfModifiedPipeline(ICacheableSpecification cacheableSpecification)
{
_cacheableSpecification = cacheableSpecification;
}
public void Register(IPipelines pipelines)
{
pipelines.BeforeRequest.AddItemToStartOfPipeline(Handle);
}
private Response Handle(NancyContext context)
{
if (_cacheableSpecification.IsCacheable(context) && context.Request.Headers.IfModifiedSince.HasValue)
{
var response = new Response { ContentType = MimeTypes.GetMimeType(context.Request.Path), StatusCode = HttpStatusCode.NotModified };
response.Headers.EnableCache();
return response;
}
return null;
}
}
}

View File

@ -1,16 +1,28 @@
using System; using System;
using Nancy; using Nancy;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Api.Frontend namespace NzbDrone.Api.Frontend
{ {
public class IsCacheableSpecification public interface ICacheableSpecification
{ {
public bool IsCacheable(Request request) bool IsCacheable(NancyContext context);
{ }
if (request.Path.Contains(".")) return false;
if (request.Path.StartsWith("/api", StringComparison.CurrentCultureIgnoreCase)) return false;
if (request.Path.StartsWith("/signalr", StringComparison.CurrentCultureIgnoreCase)) return false;
public class CacheableSpecification : ICacheableSpecification
{
public bool IsCacheable(NancyContext context)
{
if (context.Request.Query.v == BuildInfo.Version) return true;
if (context.Request.Path.StartsWith("/api", StringComparison.CurrentCultureIgnoreCase)) return false;
if (context.Request.Path.StartsWith("/signalr", StringComparison.CurrentCultureIgnoreCase)) return false;
if (context.Request.Path.EndsWith("app.js")) return false;
if (context.Response != null)
{
if (context.Response.ContentType.Contains("text/html")) return false;
}
return true; return true;
} }

View File

@ -61,8 +61,6 @@ namespace NzbDrone.Api.Frontend
if (_diskProvider.FileExists(filePath, _caseSensitive)) if (_diskProvider.FileExists(filePath, _caseSensitive))
{ {
var response = new StreamResponse(() => File.OpenRead(filePath), MimeTypes.GetMimeType(filePath)); var response = new StreamResponse(() => File.OpenRead(filePath), MimeTypes.GetMimeType(filePath));
//_addCacheHeaders.ToResponse(context.Request, response);
return response; return response;
} }

View File

@ -1,9 +1,11 @@
using NLog; using System;
using NLog;
using Nancy.Bootstrapper; using Nancy.Bootstrapper;
using Nancy.Diagnostics; using Nancy.Diagnostics;
using NzbDrone.Api.Authentication; using NzbDrone.Api.Authentication;
using NzbDrone.Api.ErrorManagement; using NzbDrone.Api.ErrorManagement;
using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions;
using NzbDrone.Api.Extensions.Pipelines;
using NzbDrone.Common.Messaging; using NzbDrone.Common.Messaging;
using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Lifecycle; using NzbDrone.Core.Lifecycle;
@ -26,23 +28,34 @@ namespace NzbDrone.Api
{ {
_logger.Info("Starting NzbDrone API"); _logger.Info("Starting NzbDrone API");
RegisterPipelines(pipelines);
container.Resolve<DatabaseTarget>().Register(); container.Resolve<DatabaseTarget>().Register();
container.Resolve<IEnableBasicAuthInNancy>().Register(pipelines); container.Resolve<IEnableBasicAuthInNancy>().Register(pipelines);
container.Resolve<IMessageAggregator>().PublishEvent(new ApplicationStartedEvent()); container.Resolve<IMessageAggregator>().PublishEvent(new ApplicationStartedEvent());
pipelines.AfterRequest.AddItemToStartOfPipeline(GzipCompressionPipeline.Handle);
pipelines.AfterRequest.AddItemToEndOfPipeline(CacheHeaderPipeline.Handle);
ApplicationPipelines.OnError.AddItemToEndOfPipeline(container.Resolve<NzbDroneErrorPipeline>().HandleException); ApplicationPipelines.OnError.AddItemToEndOfPipeline(container.Resolve<NzbDroneErrorPipeline>().HandleException);
} }
private void RegisterPipelines(IPipelines pipelines)
{
var pipelineRegistrars = _tinyIoCContainer.ResolveAll<IRegisterNancyPipeline>();
foreach (var registerNancyPipeline in pipelineRegistrars)
{
registerNancyPipeline.Register(pipelines);
}
}
protected override TinyIoCContainer GetApplicationContainer() protected override TinyIoCContainer GetApplicationContainer()
{ {
return _tinyIoCContainer; return _tinyIoCContainer;
} }
protected override DiagnosticsConfiguration DiagnosticsConfiguration protected override DiagnosticsConfiguration DiagnosticsConfiguration
{ {
get { return new DiagnosticsConfiguration { Password = @"password" }; } get { return new DiagnosticsConfiguration { Password = @"password" }; }

View File

@ -91,8 +91,10 @@
<Compile Include="Episodes\EpisodeModule.cs" /> <Compile Include="Episodes\EpisodeModule.cs" />
<Compile Include="Episodes\EpisodeResource.cs" /> <Compile Include="Episodes\EpisodeResource.cs" />
<Compile Include="Episodes\EpisodeConnection.cs" /> <Compile Include="Episodes\EpisodeConnection.cs" />
<Compile Include="Extensions\CacheHeaderPipeline.cs" /> <Compile Include="Extensions\Pipelines\CacheHeaderPipeline.cs" />
<Compile Include="Extensions\GZipPipeline.cs" /> <Compile Include="Extensions\Pipelines\GZipPipeline.cs" />
<Compile Include="Extensions\Pipelines\IfModifiedPipeline.cs" />
<Compile Include="Extensions\Pipelines\IRegisterNancyPipeline.cs" />
<Compile Include="Extensions\NancyJsonSerializer.cs" /> <Compile Include="Extensions\NancyJsonSerializer.cs" />
<Compile Include="Frontend\IAddCacheHeaders.cs" /> <Compile Include="Frontend\IAddCacheHeaders.cs" />
<Compile Include="Frontend\IsCacheableSpecification.cs" /> <Compile Include="Frontend\IsCacheableSpecification.cs" />

View File

@ -13,7 +13,6 @@ namespace NzbDrone.Common
{ {
string DownloadString(string url); string DownloadString(string url);
string DownloadString(string url, string username, string password); string DownloadString(string url, string username, string password);
string DownloadString(string url, ICredentials identity);
Dictionary<string, string> GetHeader(string url); Dictionary<string, string> GetHeader(string url);
Stream DownloadStream(string url, NetworkCredential credential = null); Stream DownloadStream(string url, NetworkCredential credential = null);
@ -44,7 +43,7 @@ namespace NzbDrone.Common
return DownloadString(url, new NetworkCredential(username, password)); return DownloadString(url, new NetworkCredential(username, password));
} }
public string DownloadString(string url, ICredentials identity) private string DownloadString(string url, ICredentials identity)
{ {
try try
{ {