Browse Source

Switched to MEF to register http handlers

LukePulverenti Luke Pulverenti luke pulverenti 12 năm trước cách đây
mục cha
commit
93b42641d2
26 tập tin đã thay đổi với 240 bổ sung154 xóa
  1. 6 0
      MediaBrowser.Api/ApiService.cs
  2. 11 2
      MediaBrowser.Api/HttpHandlers/AudioHandler.cs
  3. 6 6
      MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs
  4. 8 0
      MediaBrowser.Api/HttpHandlers/GenreHandler.cs
  5. 8 0
      MediaBrowser.Api/HttpHandlers/GenresHandler.cs
  6. 8 0
      MediaBrowser.Api/HttpHandlers/ImageHandler.cs
  7. 8 0
      MediaBrowser.Api/HttpHandlers/ItemHandler.cs
  8. 8 0
      MediaBrowser.Api/HttpHandlers/ItemListHandler.cs
  9. 8 0
      MediaBrowser.Api/HttpHandlers/PersonHandler.cs
  10. 10 3
      MediaBrowser.Api/HttpHandlers/PluginAssemblyHandler.cs
  11. 12 4
      MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs
  12. 12 4
      MediaBrowser.Api/HttpHandlers/PluginsHandler.cs
  13. 12 4
      MediaBrowser.Api/HttpHandlers/ServerConfigurationHandler.cs
  14. 8 0
      MediaBrowser.Api/HttpHandlers/StudioHandler.cs
  15. 8 0
      MediaBrowser.Api/HttpHandlers/StudiosHandler.cs
  16. 8 0
      MediaBrowser.Api/HttpHandlers/UserAuthenticationHandler.cs
  17. 8 0
      MediaBrowser.Api/HttpHandlers/UserHandler.cs
  18. 8 0
      MediaBrowser.Api/HttpHandlers/UsersHandler.cs
  19. 12 3
      MediaBrowser.Api/HttpHandlers/VideoHandler.cs
  20. 11 3
      MediaBrowser.Api/HttpHandlers/WeatherHandler.cs
  21. 8 0
      MediaBrowser.Api/HttpHandlers/YearHandler.cs
  22. 8 0
      MediaBrowser.Api/HttpHandlers/YearsHandler.cs
  23. 1 119
      MediaBrowser.Api/Plugin.cs
  24. 32 0
      MediaBrowser.Common/Kernel/BaseKernel.cs
  25. 4 4
      MediaBrowser.Common/Net/Handlers/BaseHandler.cs
  26. 7 2
      MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs

+ 6 - 0
MediaBrowser.Api/ApiService.cs

@@ -5,6 +5,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using System.Net;
 
 namespace MediaBrowser.Api
 {
@@ -374,5 +375,10 @@ namespace MediaBrowser.Api
                 LastLoginDate = user.LastLoginDate
             };
         }
+
+        public static bool IsApiUrlMatch(string url, HttpListenerRequest request)
+        {
+            return request.Url.LocalPath.EndsWith(url, StringComparison.OrdinalIgnoreCase);
+        }
     }
 }

+ 11 - 2
MediaBrowser.Api/HttpHandlers/AudioHandler.cs

@@ -1,15 +1,24 @@
-using System.Collections.Generic;
+using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Model.Entities;
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.Linq;
-using MediaBrowser.Model.Entities;
+using System.Net;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
     /// <summary>
     /// Supported output formats are: mp3,flac,ogg,wav,asf,wma,aac
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class AudioHandler : BaseMediaHandler<Audio>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("audio", request);
+        }
+
         /// <summary>
         /// Overriding to provide mp3 as a default, since pretty much every device supports it
         /// </summary>

+ 6 - 6
MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs

@@ -1,15 +1,15 @@
-using System;
+using MediaBrowser.Common.Logging;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Controller;
+using MediaBrowser.Model.Entities;
+using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
-using MediaBrowser.Common.Logging;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Net.Handlers;
-using MediaBrowser.Controller;
-using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Api.HttpHandlers
 {

+ 8 - 0
MediaBrowser.Api/HttpHandlers/GenreHandler.cs

@@ -4,7 +4,9 @@ using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
@@ -12,8 +14,14 @@ namespace MediaBrowser.Api.HttpHandlers
     /// <summary>
     /// Gets a single genre
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class GenreHandler : BaseSerializationHandler<IBNItem>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("genre", request);
+        }
+        
         protected override Task<IBNItem> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;

+ 8 - 0
MediaBrowser.Api/HttpHandlers/GenresHandler.cs

@@ -3,13 +3,21 @@ using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     public class GenresHandler : BaseSerializationHandler<IBNItem[]>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("genres", request);
+        }
+        
         protected override Task<IBNItem[]> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;

+ 8 - 0
MediaBrowser.Api/HttpHandlers/ImageHandler.cs

@@ -4,14 +4,22 @@ using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
 using System;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     public class ImageHandler : BaseHandler
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("image", request);
+        }
+        
         private string _ImagePath = null;
         private async Task<string> GetImagePath()
         {

+ 8 - 0
MediaBrowser.Api/HttpHandlers/ItemHandler.cs

@@ -1,12 +1,20 @@
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     public class ItemHandler : BaseSerializationHandler<DTOBaseItem>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("item", request);
+        }
+        
         protected override Task<DTOBaseItem> GetObjectToSerialize()
         {
             User user = ApiService.GetUserById(QueryString["userid"], true);

+ 8 - 0
MediaBrowser.Api/HttpHandlers/ItemListHandler.cs

@@ -3,13 +3,21 @@ using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     public class ItemListHandler : BaseSerializationHandler<DTOBaseItem[]>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("itemlist", request);
+        }
+        
         protected override Task<DTOBaseItem[]> GetObjectToSerialize()
         {
             User user = ApiService.GetUserById(QueryString["userid"], true);

+ 8 - 0
MediaBrowser.Api/HttpHandlers/PersonHandler.cs

@@ -3,6 +3,8 @@ using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
@@ -10,8 +12,14 @@ namespace MediaBrowser.Api.HttpHandlers
     /// <summary>
     /// Gets a single Person
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class PersonHandler : BaseSerializationHandler<IBNItem>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("person", request);
+        }
+        
         protected override Task<IBNItem> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;

+ 10 - 3
MediaBrowser.Api/HttpHandlers/PluginAssemblyHandler.cs

@@ -1,14 +1,21 @@
-using System;
+using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Controller;
+using System;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.Net;
 using System.Threading.Tasks;
-using MediaBrowser.Common.Net.Handlers;
-using MediaBrowser.Controller;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     class PluginAssemblyHandler : BaseHandler
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("pluginassembly", request);
+        }
+        
         public override Task<string> GetContentType()
         {
             throw new NotImplementedException();

+ 12 - 4
MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs

@@ -1,15 +1,23 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Plugins;
+using System;
+using System.ComponentModel.Composition;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     public class PluginConfigurationHandler : BaseSerializationHandler<BasePluginConfiguration>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("pluginconfiguration", request);
+        }
+        
         private BasePlugin _Plugin = null;
         private BasePlugin Plugin
         {

+ 12 - 4
MediaBrowser.Api/HttpHandlers/PluginsHandler.cs

@@ -1,17 +1,25 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
     /// <summary>
     /// Provides information about installed plugins
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class PluginsHandler : BaseSerializationHandler<IEnumerable<PluginInfo>>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("plugins", request);
+        }
+        
         protected override Task<IEnumerable<PluginInfo>> GetObjectToSerialize()
         {
             var plugins = Kernel.Instance.Plugins.Select(p =>

+ 12 - 4
MediaBrowser.Api/HttpHandlers/ServerConfigurationHandler.cs

@@ -1,14 +1,22 @@
-using System;
-using System.IO;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Configuration;
+using System;
+using System.ComponentModel.Composition;
+using System.IO;
+using System.Net;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     class ServerConfigurationHandler : BaseSerializationHandler<ServerConfiguration>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("serverconfiguration", request);
+        }
+        
         protected override Task<ServerConfiguration> GetObjectToSerialize()
         {
             return Task.FromResult<ServerConfiguration>(Kernel.Instance.Configuration);

+ 8 - 0
MediaBrowser.Api/HttpHandlers/StudioHandler.cs

@@ -4,7 +4,9 @@ using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
@@ -12,8 +14,14 @@ namespace MediaBrowser.Api.HttpHandlers
     /// <summary>
     /// Gets a single studio
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class StudioHandler : BaseSerializationHandler<IBNItem>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("studio", request);
+        }
+        
         protected override Task<IBNItem> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;

+ 8 - 0
MediaBrowser.Api/HttpHandlers/StudiosHandler.cs

@@ -3,13 +3,21 @@ using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     public class StudiosHandler : BaseSerializationHandler<IBNItem[]>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("studios", request);
+        }
+        
         protected override Task<IBNItem[]> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;

+ 8 - 0
MediaBrowser.Api/HttpHandlers/UserAuthenticationHandler.cs

@@ -1,12 +1,20 @@
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     class UserAuthenticationHandler : BaseSerializationHandler<AuthenticationResult>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("UserAuthentication", request);
+        }
+        
         protected override async Task<AuthenticationResult> GetObjectToSerialize()
         {
             string userId = await GetFormValue("userid").ConfigureAwait(false);

+ 8 - 0
MediaBrowser.Api/HttpHandlers/UserHandler.cs

@@ -1,12 +1,20 @@
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     class UserHandler : BaseSerializationHandler<DTOUser>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("user", request);
+        }
+        
         protected override Task<DTOUser> GetObjectToSerialize()
         {
             string id = QueryString["id"];

+ 8 - 0
MediaBrowser.Api/HttpHandlers/UsersHandler.cs

@@ -2,13 +2,21 @@
 using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     class UsersHandler : BaseSerializationHandler<IEnumerable<DTOUser>>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("users", request);
+        }
+        
         protected override Task<IEnumerable<DTOUser>> GetObjectToSerialize()
         {
             return Task.FromResult<IEnumerable<DTOUser>>(Kernel.Instance.Users.Select(u => ApiService.GetDTOUser(u)));

+ 12 - 3
MediaBrowser.Api/HttpHandlers/VideoHandler.cs

@@ -1,18 +1,27 @@
-using System;
+using MediaBrowser.Common.Drawing;
+using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Model.Entities;
+using System;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Drawing;
 using System.IO;
 using System.Linq;
-using MediaBrowser.Common.Drawing;
-using MediaBrowser.Model.Entities;
+using System.Net;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
     /// <summary>
     /// Supported output formats: mkv,m4v,mp4,asf,wmv,mov,webm,ogv,3gp,avi,ts,flv
     /// </summary>
+    [Export(typeof(BaseHandler))]
     class VideoHandler : BaseMediaHandler<Video>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("video", request);
+        }
+        
         /// <summary>
         /// We can output these files directly, but we can't encode them
         /// </summary>

+ 11 - 3
MediaBrowser.Api/HttpHandlers/WeatherHandler.cs

@@ -1,13 +1,21 @@
-using System;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Weather;
+using System;
+using System.ComponentModel.Composition;
+using System.Net;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     class WeatherHandler : BaseSerializationHandler<WeatherInfo>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("weather", request);
+        }
+        
         protected override Task<WeatherInfo> GetObjectToSerialize()
         {
             // If a specific zip code was requested on the query string, use that. Otherwise use the value from configuration

+ 8 - 0
MediaBrowser.Api/HttpHandlers/YearHandler.cs

@@ -3,6 +3,8 @@ using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
@@ -10,8 +12,14 @@ namespace MediaBrowser.Api.HttpHandlers
     /// <summary>
     /// Gets a single year
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class YearHandler : BaseSerializationHandler<IBNItem>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("year", request);
+        }
+        
         protected override Task<IBNItem> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;

+ 8 - 0
MediaBrowser.Api/HttpHandlers/YearsHandler.cs

@@ -3,13 +3,21 @@ using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
+    [Export(typeof(BaseHandler))]
     public class YearsHandler : BaseSerializationHandler<IBNItem[]>
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("years", request);
+        }
+        
         protected override Task<IBNItem[]> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;

+ 1 - 119
MediaBrowser.Api/Plugin.cs

@@ -1,12 +1,6 @@
-using MediaBrowser.Api.HttpHandlers;
-using MediaBrowser.Common.Net.Handlers;
-using MediaBrowser.Common.Plugins;
-using MediaBrowser.Controller;
+using MediaBrowser.Common.Plugins;
 using MediaBrowser.Model.Plugins;
-using System;
 using System.ComponentModel.Composition;
-using System.Net;
-using System.Reactive.Linq;
 
 namespace MediaBrowser.Api
 {
@@ -17,117 +11,5 @@ namespace MediaBrowser.Api
         {
             get { return "Media Browser API"; }
         }
-
-        protected override void InitializeOnServer()
-        {
-            var httpServer = Kernel.Instance.HttpServer;
-
-            httpServer.Where(ctx => ctx.Request.Url.LocalPath.IndexOf("/api/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe((ctx) =>
-            {
-                BaseHandler handler = GetHandler(ctx);
-
-                if (handler != null)
-                {
-                    handler.ProcessRequest(ctx);
-                }
-            });
-        }
-
-        private BaseHandler GetHandler(HttpListenerContext ctx)
-        {
-            string localPath = ctx.Request.Url.LocalPath;
-
-            if (IsUrlMatch("/api/item", localPath))
-            {
-                return new ItemHandler();
-            }
-            else if (IsUrlMatch("/api/image", localPath))
-            {
-                return new ImageHandler();
-            }
-            else if (IsUrlMatch("/api/users", localPath))
-            {
-                return new UsersHandler();
-            }
-            else if (IsUrlMatch("/api/itemlist", localPath))
-            {
-                return new ItemListHandler();
-            }
-            else if (IsUrlMatch("/api/genres", localPath))
-            {
-                return new GenresHandler();
-            }
-            else if (IsUrlMatch("/api/years", localPath))
-            {
-                return new YearsHandler();
-            }
-            else if (IsUrlMatch("/api/studios", localPath))
-            {
-                return new StudiosHandler();
-            }
-            else if (IsUrlMatch("/api/plugins", localPath))
-            {
-                return new PluginsHandler();
-            }
-            else if (IsUrlMatch("/api/pluginconfiguration", localPath))
-            {
-                return new PluginConfigurationHandler();
-            }
-            else if (IsUrlMatch("/api/static", localPath))
-            {
-                return new StaticFileHandler();
-            }
-            else if (IsUrlMatch("/api/audio", localPath))
-            {
-                return new AudioHandler();
-            }
-            else if (IsUrlMatch("/api/video", localPath))
-            {
-                return new VideoHandler();
-            }
-            else if (IsUrlMatch("/api/person", localPath))
-            {
-                return new PersonHandler();
-            }
-            else if (IsUrlMatch("/api/genre", localPath))
-            {
-                return new GenreHandler();
-            }
-            else if (IsUrlMatch("/api/year", localPath))
-            {
-                return new YearHandler();
-            }
-            else if (IsUrlMatch("/api/studio", localPath))
-            {
-                return new StudioHandler();
-            }
-            else if (IsUrlMatch("/api/weather", localPath))
-            {
-                return new WeatherHandler();
-            }
-            else if (IsUrlMatch("/api/serverconfiguration", localPath))
-            {
-                return new ServerConfigurationHandler();
-            }
-            else if (IsUrlMatch("/api/user", localPath))
-            {
-                return new UserHandler();
-            }
-            else if (IsUrlMatch("/api/pluginassembly", localPath))
-            {
-                return new PluginAssemblyHandler();
-            }
-            else if (IsUrlMatch("/api/UserAuthentication", localPath))
-            {
-                return new UserAuthenticationHandler();
-            }
-
-            return null;
-        }
-
-        private bool IsUrlMatch(string url, string localPath)
-        {
-            return localPath.EndsWith(url, StringComparison.OrdinalIgnoreCase);
-        }
     }
 }

+ 32 - 0
MediaBrowser.Common/Kernel/BaseKernel.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Common.Logging;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Common.Serialization;
 using MediaBrowser.Model.Configuration;
@@ -35,12 +36,23 @@ namespace MediaBrowser.Common.Kernel
         [ImportMany(typeof(BasePlugin))]
         public IEnumerable<BasePlugin> Plugins { get; private set; }
 
+        /// <summary>
+        /// Gets the list of currently registered http handlers
+        /// </summary>
+        [ImportMany(typeof(BaseHandler))]
+        private IEnumerable<BaseHandler> HttpHandlers { get; set; }
+
         /// <summary>
         /// Both the UI and server will have a built-in HttpServer.
         /// People will inevitably want remote control apps so it's needed in the UI too.
         /// </summary>
         public HttpServer HttpServer { get; private set; }
 
+        /// <summary>
+        /// This subscribes to HttpListener requests and finds the appropate BaseHandler to process it
+        /// </summary>
+        private IDisposable HttpListener { get; set; }
+
         protected virtual string HttpServerUrlPrefix
         {
             get
@@ -186,6 +198,21 @@ namespace MediaBrowser.Common.Kernel
             DisposeHttpServer();
 
             HttpServer = new HttpServer(HttpServerUrlPrefix);
+
+            HttpListener = HttpServer.Subscribe((ctx) =>
+            {
+                BaseHandler handler = HttpHandlers.FirstOrDefault(h => h.HandlesRequest(ctx.Request));
+
+                // Find the appropiate http handler
+                if (handler != null)
+                {
+                    // Need to create a new instance because handlers are currently stateful
+                    handler = Activator.CreateInstance(handler.GetType()) as BaseHandler;
+
+                    // No need to await this, despite the compiler warning
+                    handler.ProcessRequest(ctx);
+                }
+            });
         }
 
         /// <summary>
@@ -249,6 +276,11 @@ namespace MediaBrowser.Common.Kernel
             {
                 HttpServer.Dispose();
             }
+
+            if (HttpListener != null)
+            {
+                HttpListener.Dispose();
+            }
         }
 
         /// <summary>

+ 4 - 4
MediaBrowser.Common/Net/Handlers/BaseHandler.cs

@@ -1,4 +1,5 @@
-using System;
+using MediaBrowser.Common.Logging;
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Specialized;
@@ -6,15 +7,14 @@ using System.IO;
 using System.IO.Compression;
 using System.Linq;
 using System.Net;
-using System.Text;
 using System.Threading.Tasks;
-using System.Web;
-using MediaBrowser.Common.Logging;
 
 namespace MediaBrowser.Common.Net.Handlers
 {
     public abstract class BaseHandler
     {
+        public abstract bool HandlesRequest(HttpListenerRequest request);
+
         private Stream CompressedStream { get; set; }
 
         public virtual bool? UseChunkedEncoding

+ 7 - 2
MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs

@@ -1,15 +1,20 @@
-using System;
+using MediaBrowser.Common.Logging;
+using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
-using MediaBrowser.Common.Logging;
 
 namespace MediaBrowser.Common.Net.Handlers
 {
     public class StaticFileHandler : BaseHandler
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return false;
+        }
+
         private string _Path;
         public virtual string Path
         {