diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index b4bb92cfa..b1601df05 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -215,6 +215,13 @@
+
+
+
+
+
+
+
diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
index 322cdf4f0..99ec146d7 100644
--- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -3,7 +3,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using ServiceStack;
-using ServiceStack.Host;
using System;
using System.Collections.Generic;
using System.IO;
@@ -13,6 +12,7 @@ using System.Text;
using System.Threading.Tasks;
using Emby.Server.Implementations.HttpServer;
using Emby.Server.Implementations.HttpServer.SocketSharp;
+using Emby.Server.Implementations.Services;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Security;
using MediaBrowser.Controller;
@@ -61,12 +61,15 @@ namespace Emby.Server.Implementations.HttpServer
private readonly Func> _funcParseFn;
private readonly bool _enableDualModeSockets;
+ public List> RequestFilters { get; set; }
+ private Dictionary ServiceOperationsMap = new Dictionary();
+
public HttpListenerHost(IServerApplicationHost applicationHost,
ILogger logger,
IServerConfigurationManager config,
string serviceName,
string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IJsonSerializer jsonSerializer, IXmlSerializer xmlSerializer, IEnvironmentInfo environment, ICertificate certificate, IStreamFactory streamFactory, Func> funcParseFn, bool enableDualModeSockets)
- : base(serviceName)
+ : base()
{
_appHost = applicationHost;
DefaultRedirectPath = defaultRedirectPath;
@@ -85,6 +88,8 @@ namespace Emby.Server.Implementations.HttpServer
_config = config;
_logger = logger;
+
+ RequestFilters = new List>();
}
public string GlobalResponse { get; set; }
@@ -99,18 +104,7 @@ namespace Emby.Server.Implementations.HttpServer
{typeof (ArgumentException), 400}
};
- public override void Configure()
- {
- var requestFilters = _appHost.GetExports().ToList();
- foreach (var filter in requestFilters)
- {
- GlobalRequestFilters.Add(filter.Filter);
- }
-
- GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
- }
-
- protected override ILogger Logger
+ protected ILogger Logger
{
get
{
@@ -118,32 +112,73 @@ namespace Emby.Server.Implementations.HttpServer
}
}
- public override T Resolve()
- {
- return _appHost.Resolve();
- }
-
- public override T TryResolve()
- {
- return _appHost.TryResolve();
- }
-
public override object CreateInstance(Type type)
{
return _appHost.CreateInstance(type);
}
- protected override ServiceController CreateServiceController()
+ private ServiceController CreateServiceController()
{
var types = _restServices.Select(r => r.GetType()).ToArray();
return new ServiceController(() => types);
}
- public override ServiceStackHost Start(string listeningAtUrlBase)
+ ///
+ /// Applies the request filters. Returns whether or not the request has been handled
+ /// and no more processing should be done.
+ ///
+ ///
+ public void ApplyRequestFilters(IRequest req, IResponse res, object requestDto)
{
- StartListener();
- return this;
+ //Exec all RequestFilter attributes with Priority < 0
+ var attributes = GetRequestFilterAttributes(requestDto.GetType());
+ var i = 0;
+ for (; i < attributes.Length && attributes[i].Priority < 0; i++)
+ {
+ var attribute = attributes[i];
+ attribute.RequestFilter(req, res, requestDto);
+ }
+
+ //Exec global filters
+ foreach (var requestFilter in RequestFilters)
+ {
+ requestFilter(req, res, requestDto);
+ }
+
+ //Exec remaining RequestFilter attributes with Priority >= 0
+ for (; i < attributes.Length && attributes[i].Priority >= 0; i++)
+ {
+ var attribute = attributes[i];
+ attribute.RequestFilter(req, res, requestDto);
+ }
+ }
+
+ public Type GetServiceTypeByRequest(Type requestType)
+ {
+ Type serviceType;
+ ServiceOperationsMap.TryGetValue(requestType, out serviceType);
+ return serviceType;
+ }
+
+ public void AddServiceInfo(Type serviceType, Type requestType, Type responseType)
+ {
+ ServiceOperationsMap[requestType] = serviceType;
+ }
+
+ private IHasRequestFilter[] GetRequestFilterAttributes(Type requestDtoType)
+ {
+ var attributes = requestDtoType.AllAttributes().OfType().ToList();
+
+ var serviceType = GetServiceTypeByRequest(requestDtoType);
+ if (serviceType != null)
+ {
+ attributes.AddRange(serviceType.AllAttributes().OfType());
+ }
+
+ attributes.Sort((x, y) => x.Priority - y.Priority);
+
+ return attributes.ToArray();
}
///
@@ -531,11 +566,11 @@ namespace Emby.Server.Implementations.HttpServer
return;
}
- var handler = HttpHandlerFactory.GetHandler(httpReq, _logger);
+ var handler = GetServiceHandler(httpReq);
if (handler != null)
{
- await handler.ProcessRequestAsync(httpReq, httpRes, operationName).ConfigureAwait(false);
+ await handler.ProcessRequestAsync(this, httpReq, httpRes, Logger, operationName).ConfigureAwait(false);
}
else
{
@@ -565,6 +600,35 @@ namespace Emby.Server.Implementations.HttpServer
}
}
+ // Entry point for HttpListener
+ public ServiceHandler GetServiceHandler(IHttpRequest httpReq)
+ {
+ var pathInfo = httpReq.PathInfo;
+
+ var pathParts = pathInfo.TrimStart('/').Split('/');
+ if (pathParts.Length == 0)
+ {
+ _logger.Error("Path parts empty for PathInfo: {0}, Url: {1}", pathInfo, httpReq.RawUrl);
+ return null;
+ }
+
+ string contentType;
+ var restPath = ServiceHandler.FindMatchingRestPath(httpReq.HttpMethod, pathInfo, _logger, out contentType);
+
+ if (restPath != null)
+ {
+ return new ServiceHandler
+ {
+ RestPath = restPath,
+ ResponseContentType = contentType
+ };
+ }
+
+ _logger.Error("Could not find handler for {0}", pathInfo);
+ return null;
+ }
+
+
private void Write(IResponse response, string text)
{
var bOutput = Encoding.UTF8.GetBytes(text);
@@ -580,6 +644,7 @@ namespace Emby.Server.Implementations.HttpServer
httpRes.AddHeader("Location", url);
}
+ public ServiceController ServiceController { get; private set; }
///
/// Adds the rest handlers.
@@ -593,12 +658,22 @@ namespace Emby.Server.Implementations.HttpServer
_logger.Info("Calling ServiceStack AppHost.Init");
- base.Init();
+ Instance = this;
+
+ ServiceController.Init(this);
+
+ var requestFilters = _appHost.GetExports().ToList();
+ foreach (var filter in requestFilters)
+ {
+ RequestFilters.Add(filter.Filter);
+ }
+
+ GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
}
public override RouteAttribute[] GetRouteAttributes(Type requestType)
{
- var routes = base.GetRouteAttributes(requestType).ToList();
+ var routes = requestType.AllAttributes();
var clone = routes.ToList();
foreach (var route in clone)
@@ -628,33 +703,6 @@ namespace Emby.Server.Implementations.HttpServer
return routes.ToArray();
}
- public override object GetTaskResult(Task task, string requestName)
- {
- try
- {
- var taskObject = task as Task