moved static resource to basic nancy module.

cache and gzip piplelines are missing
This commit is contained in:
Keivan Beigi 2013-08-19 19:31:26 -07:00
parent 93b0cf4be9
commit 24ba4390a1
12 changed files with 185 additions and 145 deletions

View File

@ -1,72 +0,0 @@
using System;
using System.IO;
using Nancy;
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
{
private readonly IDiskProvider _diskProvider;
private readonly ICached<string> _indexCache;
private readonly string _indexPath;
public IndexModule(IDiskProvider diskProvider, ICacheManger cacheManger, IAppFolderInfo appFolder)
{
_diskProvider = diskProvider;
_indexPath = Path.Combine(appFolder.StartUpFolder, "UI", "index.html");
_indexCache = cacheManger.GetCache<string>(typeof(IndexModule));
//Serve anything that doesn't have an extension
Get[@"/(.*)"] = x => Index();
}
private object Index()
{
if (
Request.Path.Contains(".")
|| Request.Path.StartsWith("/static", StringComparison.CurrentCultureIgnoreCase)
|| Request.Path.StartsWith("/api", StringComparison.CurrentCultureIgnoreCase)
|| Request.Path.StartsWith("/signalr", StringComparison.CurrentCultureIgnoreCase))
{
return new NotFoundResponse();
}
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;
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using Nancy;
namespace NzbDrone.Api.Frontend
{
public class IsCacheableSpecification
{
public bool IsCacheable(Request request)
{
if (request.Path.Contains(".")) return false;
if (request.Path.StartsWith("/api", StringComparison.CurrentCultureIgnoreCase)) return false;
if (request.Path.StartsWith("/signalr", StringComparison.CurrentCultureIgnoreCase)) return false;
return true;
}
}
}

View File

@ -1,5 +1,5 @@

namespace NzbDrone.Api.Frontend
namespace NzbDrone.Api.Frontend.Mappers
{
public interface IMapHttpRequestsToDisk
{

View File

@ -0,0 +1,25 @@
using System.IO;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Api.Frontend.Mappers
{
public class IndexHtmlMapper : IMapHttpRequestsToDisk
{
private readonly string _indexPath;
public IndexHtmlMapper(IAppFolderInfo appFolderInfo)
{
_indexPath = Path.Combine(appFolderInfo.StartUpFolder, "UI", "index.html");
}
public string Map(string resourceUrl)
{
return _indexPath;
}
public bool CanHandle(string resourceUrl)
{
return !resourceUrl.Contains(".");
}
}
}

View File

@ -2,7 +2,7 @@ using System.IO;
using NzbDrone.Common;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Api.Frontend
namespace NzbDrone.Api.Frontend.Mappers
{
public class LogFileMapper : IMapHttpRequestsToDisk
{

View File

@ -2,7 +2,7 @@ using System.IO;
using NzbDrone.Common;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Api.Frontend
namespace NzbDrone.Api.Frontend.Mappers
{
public class MediaCoverMapper : IMapHttpRequestsToDisk
{

View File

@ -0,0 +1,28 @@
using System.IO;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Api.Frontend.Mappers
{
public class StaticResourceMapper : IMapHttpRequestsToDisk
{
private readonly IAppFolderInfo _appFolderInfo;
public StaticResourceMapper(IAppFolderInfo appFolderInfo)
{
_appFolderInfo = appFolderInfo;
}
public string Map(string resourceUrl)
{
var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar);
path = path.Trim(Path.DirectorySeparatorChar);
return Path.Combine(_appFolderInfo.StartUpFolder, "UI", path);
}
public bool CanHandle(string resourceUrl)
{
return resourceUrl.StartsWith("/Content") || resourceUrl.EndsWith(".js") || resourceUrl.EndsWith(".css");
}
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.IO;
using System.Linq;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Api.Frontend
{
public class StaticResourceMapper : IMapHttpRequestsToDisk
{
private readonly IAppFolderInfo _appFolderInfo;
private static readonly string[] Extensions = new[] {
".css",
".js",
".html",
".htm",
".jpg",
".jpeg",
".ico",
".icon",
".gif",
".png",
".woff",
".ttf",
".eot"
};
public StaticResourceMapper(IAppFolderInfo appFolderInfo)
{
_appFolderInfo = appFolderInfo;
}
public string Map(string resourceUrl)
{
var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar);
path = path.Trim(Path.DirectorySeparatorChar);
return Path.Combine(_appFolderInfo.StartUpFolder, "UI", path);
}
public bool CanHandle(string resourceUrl)
{
if (string.IsNullOrWhiteSpace(resourceUrl))
{
return false;
}
if (resourceUrl.StartsWith("/mediacover", StringComparison.CurrentCultureIgnoreCase))
{
return false;
}
return Extensions.Any(resourceUrl.EndsWith);
}
}
}

View File

@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NLog;
using Nancy;
using Nancy.Responses;
using NzbDrone.Api.Frontend.Mappers;
using NzbDrone.Common;
using NzbDrone.Common.Cache;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Api.Frontend
{
public class StaticResourceModule : NancyModule
{
private readonly IDiskProvider _diskProvider;
private readonly IEnumerable<IMapHttpRequestsToDisk> _requestMappers;
private readonly Logger _logger;
private readonly ICached<string> _indexCache;
private readonly bool _caseSensitive;
public StaticResourceModule(IDiskProvider diskProvider, ICacheManger cacheManger, IEnumerable<IMapHttpRequestsToDisk> requestMappers, Logger logger)
{
_diskProvider = diskProvider;
_requestMappers = requestMappers;
_logger = logger;
_indexCache = cacheManger.GetCache<string>(typeof(StaticResourceModule));
Get["/{resource*}"] = x => Index();
Get["/*"] = x => Index();
if (!RuntimeInfo.IsProduction)
{
_caseSensitive = true;
}
}
private Response Index()
{
var path = Request.Url.Path;
if (
string.IsNullOrWhiteSpace(path) ||
path.StartsWith("/api", StringComparison.CurrentCultureIgnoreCase) ||
path.StartsWith("/signalr", StringComparison.CurrentCultureIgnoreCase))
{
return null;
}
var mapper = _requestMappers.SingleOrDefault(m => m.CanHandle(path));
if (mapper != null)
{
var filePath = mapper.Map(path);
if (_diskProvider.FileExists(filePath, _caseSensitive))
{
var response = new StreamResponse(() => File.OpenRead(filePath), MimeTypes.GetMimeType(filePath));
//_addCacheHeaders.ToResponse(context.Request, response);
return response;
}
_logger.Warn("File {0} not found", filePath);
}
else
{
_logger.Warn("Couldn't find handler for {0}", path);
}
return new NotFoundResponse();
/* 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();
}
/* 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;
}*/
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using NLog;
using Nancy;
using Nancy.Responses;
using NzbDrone.Api.Frontend.Mappers;
using NzbDrone.Common;
using NzbDrone.Common.EnvironmentInfo;

View File

@ -1,11 +1,9 @@
using NLog;
using Nancy.Bootstrapper;
using Nancy.Conventions;
using Nancy.Diagnostics;
using NzbDrone.Api.Authentication;
using NzbDrone.Api.ErrorManagement;
using NzbDrone.Api.Extensions;
using NzbDrone.Api.Frontend;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Lifecycle;
@ -50,13 +48,6 @@ namespace NzbDrone.Api
get { return new DiagnosticsConfiguration { Password = @"password" }; }
}
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
base.ConfigureConventions(nancyConventions);
var processors = ApplicationContainer.Resolve<IProcessStaticResource>();
Conventions.StaticContentsConventions.Add(processors.ProcessStaticResourceRequest);
}
protected override byte[] FavIcon
{
get

View File

@ -94,13 +94,15 @@
<Compile Include="Extensions\CacheHeaderPipeline.cs" />
<Compile Include="Extensions\GZipPipeline.cs" />
<Compile Include="Extensions\NancyJsonSerializer.cs" />
<Compile Include="Frontend\LogFileMapper.cs" />
<Compile Include="Frontend\IAddCacheHeaders.cs" />
<Compile Include="Frontend\MediaCoverMapper.cs" />
<Compile Include="Frontend\IMapHttpRequestsToDisk.cs" />
<Compile Include="Frontend\IndexModule.cs" />
<Compile Include="Frontend\IsCacheableSpecification.cs" />
<Compile Include="Frontend\Mappers\IndexHtmlMapper.cs" />
<Compile Include="Frontend\Mappers\LogFileMapper.cs" />
<Compile Include="Frontend\Mappers\MediaCoverMapper.cs" />
<Compile Include="Frontend\Mappers\StaticResourceMapper.cs" />
<Compile Include="Frontend\Mappers\IMapHttpRequestsToDisk.cs" />
<Compile Include="Frontend\StaticResourceModule.cs" />
<Compile Include="Frontend\StaticResourceProvider.cs" />
<Compile Include="Frontend\StaticResourceMapper.cs" />
<Compile Include="History\HistoryResource.cs" />
<Compile Include="History\HistoryModule.cs" />
<Compile Include="Indexers\IndexerSchemaModule.cs" />