2
0
Эх сурвалжийг харах

Switched to MEF to register http handlers

LukePulverenti Luke Pulverenti luke pulverenti 12 жил өмнө
parent
commit
93b42641d2
26 өөрчлөгдсөн 240 нэмэгдсэн , 154 устгасан
  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.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using System.Net;
 
 
 namespace MediaBrowser.Api
 namespace MediaBrowser.Api
 {
 {
@@ -374,5 +375,10 @@ namespace MediaBrowser.Api
                 LastLoginDate = user.LastLoginDate
                 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.IO;
 using System.Linq;
 using System.Linq;
-using MediaBrowser.Model.Entities;
+using System.Net;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
     /// <summary>
     /// <summary>
     /// Supported output formats are: mp3,flac,ogg,wav,asf,wma,aac
     /// Supported output formats are: mp3,flac,ogg,wav,asf,wma,aac
     /// </summary>
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class AudioHandler : BaseMediaHandler<Audio>
     public class AudioHandler : BaseMediaHandler<Audio>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("audio", request);
+        }
+
         /// <summary>
         /// <summary>
         /// Overriding to provide mp3 as a default, since pretty much every device supports it
         /// Overriding to provide mp3 as a default, since pretty much every device supports it
         /// </summary>
         /// </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.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Net;
 using System.Net;
 using System.Threading.Tasks;
 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
 namespace MediaBrowser.Api.HttpHandlers
 {
 {

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

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

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

@@ -1,12 +1,20 @@
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     public class ItemHandler : BaseSerializationHandler<DTOBaseItem>
     public class ItemHandler : BaseSerializationHandler<DTOBaseItem>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("item", request);
+        }
+        
         protected override Task<DTOBaseItem> GetObjectToSerialize()
         protected override Task<DTOBaseItem> GetObjectToSerialize()
         {
         {
             User user = ApiService.GetUserById(QueryString["userid"], true);
             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 MediaBrowser.Model.Entities;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     public class ItemListHandler : BaseSerializationHandler<DTOBaseItem[]>
     public class ItemListHandler : BaseSerializationHandler<DTOBaseItem[]>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("itemlist", request);
+        }
+        
         protected override Task<DTOBaseItem[]> GetObjectToSerialize()
         protected override Task<DTOBaseItem[]> GetObjectToSerialize()
         {
         {
             User user = ApiService.GetUserById(QueryString["userid"], true);
             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.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
@@ -10,8 +12,14 @@ namespace MediaBrowser.Api.HttpHandlers
     /// <summary>
     /// <summary>
     /// Gets a single Person
     /// Gets a single Person
     /// </summary>
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class PersonHandler : BaseSerializationHandler<IBNItem>
     public class PersonHandler : BaseSerializationHandler<IBNItem>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("person", request);
+        }
+        
         protected override Task<IBNItem> GetObjectToSerialize()
         protected override Task<IBNItem> GetObjectToSerialize()
         {
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             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.IO;
 using System.Net;
 using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using MediaBrowser.Common.Net.Handlers;
-using MediaBrowser.Controller;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     class PluginAssemblyHandler : BaseHandler
     class PluginAssemblyHandler : BaseHandler
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("pluginassembly", request);
+        }
+        
         public override Task<string> GetContentType()
         public override Task<string> GetContentType()
         {
         {
             throw new NotImplementedException();
             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.Common.Plugins;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Plugins;
+using System;
+using System.ComponentModel.Composition;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     public class PluginConfigurationHandler : BaseSerializationHandler<BasePluginConfiguration>
     public class PluginConfigurationHandler : BaseSerializationHandler<BasePluginConfiguration>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("pluginconfiguration", request);
+        }
+        
         private BasePlugin _Plugin = null;
         private BasePlugin _Plugin = null;
         private BasePlugin Plugin
         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.Controller;
 using MediaBrowser.Model.DTO;
 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
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
     /// <summary>
     /// <summary>
     /// Provides information about installed plugins
     /// Provides information about installed plugins
     /// </summary>
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class PluginsHandler : BaseSerializationHandler<IEnumerable<PluginInfo>>
     public class PluginsHandler : BaseSerializationHandler<IEnumerable<PluginInfo>>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("plugins", request);
+        }
+        
         protected override Task<IEnumerable<PluginInfo>> GetObjectToSerialize()
         protected override Task<IEnumerable<PluginInfo>> GetObjectToSerialize()
         {
         {
             var plugins = Kernel.Instance.Plugins.Select(p =>
             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.Controller;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Configuration;
+using System;
+using System.ComponentModel.Composition;
+using System.IO;
+using System.Net;
+using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     class ServerConfigurationHandler : BaseSerializationHandler<ServerConfiguration>
     class ServerConfigurationHandler : BaseSerializationHandler<ServerConfiguration>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("serverconfiguration", request);
+        }
+        
         protected override Task<ServerConfiguration> GetObjectToSerialize()
         protected override Task<ServerConfiguration> GetObjectToSerialize()
         {
         {
             return Task.FromResult<ServerConfiguration>(Kernel.Instance.Configuration);
             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 MediaBrowser.Model.Entities;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
@@ -12,8 +14,14 @@ namespace MediaBrowser.Api.HttpHandlers
     /// <summary>
     /// <summary>
     /// Gets a single studio
     /// Gets a single studio
     /// </summary>
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class StudioHandler : BaseSerializationHandler<IBNItem>
     public class StudioHandler : BaseSerializationHandler<IBNItem>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("studio", request);
+        }
+        
         protected override Task<IBNItem> GetObjectToSerialize()
         protected override Task<IBNItem> GetObjectToSerialize()
         {
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             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.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     public class StudiosHandler : BaseSerializationHandler<IBNItem[]>
     public class StudiosHandler : BaseSerializationHandler<IBNItem[]>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("studios", request);
+        }
+        
         protected override Task<IBNItem[]> GetObjectToSerialize()
         protected override Task<IBNItem[]> GetObjectToSerialize()
         {
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             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.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     class UserAuthenticationHandler : BaseSerializationHandler<AuthenticationResult>
     class UserAuthenticationHandler : BaseSerializationHandler<AuthenticationResult>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("UserAuthentication", request);
+        }
+        
         protected override async Task<AuthenticationResult> GetObjectToSerialize()
         protected override async Task<AuthenticationResult> GetObjectToSerialize()
         {
         {
             string userId = await GetFormValue("userid").ConfigureAwait(false);
             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.Common.Net.Handlers;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     class UserHandler : BaseSerializationHandler<DTOUser>
     class UserHandler : BaseSerializationHandler<DTOUser>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("user", request);
+        }
+        
         protected override Task<DTOUser> GetObjectToSerialize()
         protected override Task<DTOUser> GetObjectToSerialize()
         {
         {
             string id = QueryString["id"];
             string id = QueryString["id"];

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

@@ -2,13 +2,21 @@
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     class UsersHandler : BaseSerializationHandler<IEnumerable<DTOUser>>
     class UsersHandler : BaseSerializationHandler<IEnumerable<DTOUser>>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("users", request);
+        }
+        
         protected override Task<IEnumerable<DTOUser>> GetObjectToSerialize()
         protected override Task<IEnumerable<DTOUser>> GetObjectToSerialize()
         {
         {
             return Task.FromResult<IEnumerable<DTOUser>>(Kernel.Instance.Users.Select(u => ApiService.GetDTOUser(u)));
             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.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Drawing;
 using System.Drawing;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
-using MediaBrowser.Common.Drawing;
-using MediaBrowser.Model.Entities;
+using System.Net;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
     /// <summary>
     /// <summary>
     /// Supported output formats: mkv,m4v,mp4,asf,wmv,mov,webm,ogv,3gp,avi,ts,flv
     /// Supported output formats: mkv,m4v,mp4,asf,wmv,mov,webm,ogv,3gp,avi,ts,flv
     /// </summary>
     /// </summary>
+    [Export(typeof(BaseHandler))]
     class VideoHandler : BaseMediaHandler<Video>
     class VideoHandler : BaseMediaHandler<Video>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("video", request);
+        }
+        
         /// <summary>
         /// <summary>
         /// We can output these files directly, but we can't encode them
         /// We can output these files directly, but we can't encode them
         /// </summary>
         /// </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.Controller;
 using MediaBrowser.Model.Weather;
 using MediaBrowser.Model.Weather;
+using System;
+using System.ComponentModel.Composition;
+using System.Net;
+using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     class WeatherHandler : BaseSerializationHandler<WeatherInfo>
     class WeatherHandler : BaseSerializationHandler<WeatherInfo>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("weather", request);
+        }
+        
         protected override Task<WeatherInfo> GetObjectToSerialize()
         protected override Task<WeatherInfo> GetObjectToSerialize()
         {
         {
             // If a specific zip code was requested on the query string, use that. Otherwise use the value from configuration
             // 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.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
@@ -10,8 +12,14 @@ namespace MediaBrowser.Api.HttpHandlers
     /// <summary>
     /// <summary>
     /// Gets a single year
     /// Gets a single year
     /// </summary>
     /// </summary>
+    [Export(typeof(BaseHandler))]
     public class YearHandler : BaseSerializationHandler<IBNItem>
     public class YearHandler : BaseSerializationHandler<IBNItem>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("year", request);
+        }
+        
         protected override Task<IBNItem> GetObjectToSerialize()
         protected override Task<IBNItem> GetObjectToSerialize()
         {
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             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.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.ComponentModel.Composition;
 using System.Linq;
 using System.Linq;
+using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
+    [Export(typeof(BaseHandler))]
     public class YearsHandler : BaseSerializationHandler<IBNItem[]>
     public class YearsHandler : BaseSerializationHandler<IBNItem[]>
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return ApiService.IsApiUrlMatch("years", request);
+        }
+        
         protected override Task<IBNItem[]> GetObjectToSerialize()
         protected override Task<IBNItem[]> GetObjectToSerialize()
         {
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             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 MediaBrowser.Model.Plugins;
-using System;
 using System.ComponentModel.Composition;
 using System.ComponentModel.Composition;
-using System.Net;
-using System.Reactive.Linq;
 
 
 namespace MediaBrowser.Api
 namespace MediaBrowser.Api
 {
 {
@@ -17,117 +11,5 @@ namespace MediaBrowser.Api
         {
         {
             get { return "Media Browser 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.Logging;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Common.Serialization;
 using MediaBrowser.Common.Serialization;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Configuration;
@@ -35,12 +36,23 @@ namespace MediaBrowser.Common.Kernel
         [ImportMany(typeof(BasePlugin))]
         [ImportMany(typeof(BasePlugin))]
         public IEnumerable<BasePlugin> Plugins { get; private set; }
         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>
         /// <summary>
         /// Both the UI and server will have a built-in HttpServer.
         /// 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.
         /// People will inevitably want remote control apps so it's needed in the UI too.
         /// </summary>
         /// </summary>
         public HttpServer HttpServer { get; private set; }
         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
         protected virtual string HttpServerUrlPrefix
         {
         {
             get
             get
@@ -186,6 +198,21 @@ namespace MediaBrowser.Common.Kernel
             DisposeHttpServer();
             DisposeHttpServer();
 
 
             HttpServer = new HttpServer(HttpServerUrlPrefix);
             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>
         /// <summary>
@@ -249,6 +276,11 @@ namespace MediaBrowser.Common.Kernel
             {
             {
                 HttpServer.Dispose();
                 HttpServer.Dispose();
             }
             }
+
+            if (HttpListener != null)
+            {
+                HttpListener.Dispose();
+            }
         }
         }
 
 
         /// <summary>
         /// <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;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Collections.Specialized;
 using System.Collections.Specialized;
@@ -6,15 +7,14 @@ using System.IO;
 using System.IO.Compression;
 using System.IO.Compression;
 using System.Linq;
 using System.Linq;
 using System.Net;
 using System.Net;
-using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using System.Web;
-using MediaBrowser.Common.Logging;
 
 
 namespace MediaBrowser.Common.Net.Handlers
 namespace MediaBrowser.Common.Net.Handlers
 {
 {
     public abstract class BaseHandler
     public abstract class BaseHandler
     {
     {
+        public abstract bool HandlesRequest(HttpListenerRequest request);
+
         private Stream CompressedStream { get; set; }
         private Stream CompressedStream { get; set; }
 
 
         public virtual bool? UseChunkedEncoding
         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.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Net;
 using System.Net;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using MediaBrowser.Common.Logging;
 
 
 namespace MediaBrowser.Common.Net.Handlers
 namespace MediaBrowser.Common.Net.Handlers
 {
 {
     public class StaticFileHandler : BaseHandler
     public class StaticFileHandler : BaseHandler
     {
     {
+        public override bool HandlesRequest(HttpListenerRequest request)
+        {
+            return false;
+        }
+
         private string _Path;
         private string _Path;
         public virtual string Path
         public virtual string Path
         {
         {