diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 133f22bcdd..8fcef654dd 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -1,11 +1,10 @@
-using System.Collections.Generic;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Connectivity;
using MediaBrowser.Model.Logging;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.Common.Web;
using ServiceStack.ServiceHost;
using System;
+using System.Collections.Generic;
namespace MediaBrowser.Api
{
@@ -13,8 +12,70 @@ namespace MediaBrowser.Api
/// Class BaseApiService
///
[RequestFilter]
- public class BaseApiService : BaseRestService
+ public class BaseApiService : IHasResultFactory, IRestfulService
{
+ ///
+ /// Gets or sets the logger.
+ ///
+ /// The logger.
+ public ILogger Logger { get; set; }
+
+ ///
+ /// Gets or sets the HTTP result factory.
+ ///
+ /// The HTTP result factory.
+ public IHttpResultFactory ResultFactory { get; set; }
+
+ ///
+ /// Gets or sets the request context.
+ ///
+ /// The request context.
+ public IRequestContext RequestContext { get; set; }
+
+ ///
+ /// To the optimized result.
+ ///
+ ///
+ /// The result.
+ /// System.Object.
+ protected object ToOptimizedResult(T result)
+ where T : class
+ {
+ return ResultFactory.GetOptimizedResult(RequestContext, result);
+ }
+
+ ///
+ /// To the optimized result using cache.
+ ///
+ ///
+ /// The cache key.
+ /// The last date modified.
+ /// Duration of the cache.
+ /// The factory fn.
+ /// System.Object.
+ /// cacheKey
+ protected object ToOptimizedResultUsingCache(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func factoryFn)
+ where T : class
+ {
+ return ResultFactory.GetOptimizedResultUsingCache(RequestContext, cacheKey, lastDateModified, cacheDuration, factoryFn);
+ }
+
+ ///
+ /// To the cached result.
+ ///
+ ///
+ /// The cache key.
+ /// The last date modified.
+ /// Duration of the cache.
+ /// The factory fn.
+ /// Type of the content.
+ /// System.Object.
+ /// cacheKey
+ protected object ToCachedResult(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func factoryFn, string contentType)
+ where T : class
+ {
+ return ResultFactory.GetCachedResult(RequestContext, cacheKey, lastDateModified, cacheDuration, factoryFn, contentType);
+ }
}
///
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
index d35d485360..5ba2586e36 100644
--- a/MediaBrowser.Api/EnvironmentService.cs
+++ b/MediaBrowser.Api/EnvironmentService.cs
@@ -2,7 +2,6 @@
using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
@@ -16,7 +15,7 @@ namespace MediaBrowser.Api
/// Class GetDirectoryContents
///
[Route("/Environment/DirectoryContents", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets the contents of a given directory in the file system")]
+ [Api(Description = "Gets the contents of a given directory in the file system")]
public class GetDirectoryContents : IReturn>
{
///
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 46c357579d..8498292da6 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -5,7 +5,6 @@ using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using System;
@@ -21,7 +20,7 @@ namespace MediaBrowser.Api.Images
///
[Route("/Items/{Id}/Images/{Type}", "GET")]
[Route("/Items/{Id}/Images/{Type}/{Index}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets an item image")]
+ [Api(Description = "Gets an item image")]
public class GetItemImage : ImageRequest
{
///
@@ -37,7 +36,7 @@ namespace MediaBrowser.Api.Images
///
[Route("/Persons/{Name}/Images/{Type}", "GET")]
[Route("/Persons/{Name}/Images/{Type}/{Index}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a person image")]
+ [Api(Description = "Gets a person image")]
public class GetPersonImage : ImageRequest
{
///
@@ -53,7 +52,7 @@ namespace MediaBrowser.Api.Images
///
[Route("/Studios/{Name}/Images/{Type}", "GET")]
[Route("/Studios/{Name}/Images/{Type}/{Index}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a studio image")]
+ [Api(Description = "Gets a studio image")]
public class GetStudioImage : ImageRequest
{
///
@@ -69,7 +68,7 @@ namespace MediaBrowser.Api.Images
///
[Route("/Genres/{Name}/Images/{Type}", "GET")]
[Route("/Genres/{Name}/Images/{Type}/{Index}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a genre image")]
+ [Api(Description = "Gets a genre image")]
public class GetGenreImage : ImageRequest
{
///
@@ -85,7 +84,7 @@ namespace MediaBrowser.Api.Images
///
[Route("/Years/{Year}/Images/{Type}", "GET")]
[Route("/Years/{Year}/Images/{Type}/{Index}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a year image")]
+ [Api(Description = "Gets a year image")]
public class GetYearImage : ImageRequest
{
///
@@ -101,7 +100,7 @@ namespace MediaBrowser.Api.Images
///
[Route("/Users/{Id}/Images/{Type}", "GET")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a user image")]
+ [Api(Description = "Gets a user image")]
public class GetUserImage : ImageRequest
{
///
@@ -117,7 +116,7 @@ namespace MediaBrowser.Api.Images
///
[Route("/Users/{Id}/Images/{Type}", "DELETE")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "DELETE")]
- [ServiceStack.ServiceHost.Api(Description = "Deletes a user image")]
+ [Api(Description = "Deletes a user image")]
public class DeleteUserImage : DeleteImageRequest, IReturnVoid
{
///
@@ -130,7 +129,7 @@ namespace MediaBrowser.Api.Images
[Route("/Users/{Id}/Images/{Type}", "POST")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "POST")]
- [ServiceStack.ServiceHost.Api(Description = "Posts a user image")]
+ [Api(Description = "Posts a user image")]
public class PostUserImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid
{
///
diff --git a/MediaBrowser.Api/Images/ImageWriter.cs b/MediaBrowser.Api/Images/ImageWriter.cs
index 4541a6afe4..c130364fbe 100644
--- a/MediaBrowser.Api/Images/ImageWriter.cs
+++ b/MediaBrowser.Api/Images/ImageWriter.cs
@@ -1,7 +1,9 @@
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using ServiceStack.Service;
+using ServiceStack.ServiceHost;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@@ -10,7 +12,7 @@ namespace MediaBrowser.Api.Images
///
/// Class ImageWriter
///
- public class ImageWriter : IStreamWriter
+ public class ImageWriter : IStreamWriter, IHasOptions
{
///
/// Gets or sets the request.
@@ -32,6 +34,19 @@ namespace MediaBrowser.Api.Images
///
public DateTime OriginalImageDateModified;
+ ///
+ /// The _options
+ ///
+ private readonly IDictionary _options = new Dictionary();
+ ///
+ /// Gets the options.
+ ///
+ /// The options.
+ public IDictionary Options
+ {
+ get { return _options; }
+ }
+
///
/// Writes to.
///
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 73f2243f2e..f2867b5956 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -3,7 +3,6 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
@@ -15,7 +14,7 @@ namespace MediaBrowser.Api.Library
/// Class GetPhyscialPaths
///
[Route("/Library/PhysicalPaths", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a list of physical paths from virtual folders")]
+ [Api(Description = "Gets a list of physical paths from virtual folders")]
public class GetPhyscialPaths : IReturn>
{
}
@@ -24,7 +23,7 @@ namespace MediaBrowser.Api.Library
/// Class GetItemTypes
///
[Route("/Library/ItemTypes", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a list of BaseItem types")]
+ [Api(Description = "Gets a list of BaseItem types")]
public class GetItemTypes : IReturn>
{
///
@@ -39,7 +38,7 @@ namespace MediaBrowser.Api.Library
/// Class GetPerson
///
[Route("/Persons/{Name}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a person, by name")]
+ [Api(Description = "Gets a person, by name")]
public class GetPerson : IReturn
{
///
@@ -54,7 +53,7 @@ namespace MediaBrowser.Api.Library
/// Class GetStudio
///
[Route("/Studios/{Name}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a studio, by name")]
+ [Api(Description = "Gets a studio, by name")]
public class GetStudio : IReturn
{
///
@@ -69,7 +68,7 @@ namespace MediaBrowser.Api.Library
/// Class GetGenre
///
[Route("/Genres/{Name}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a genre, by name")]
+ [Api(Description = "Gets a genre, by name")]
public class GetGenre : IReturn
{
///
@@ -84,7 +83,7 @@ namespace MediaBrowser.Api.Library
/// Class GetYear
///
[Route("/Years/{Year}", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets a year")]
+ [Api(Description = "Gets a year")]
public class GetYear : IReturn
{
///
diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index 072e37e683..a913f86872 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
index b7788326e6..54784fba8d 100644
--- a/MediaBrowser.Api/LocalizationService.cs
+++ b/MediaBrowser.Api/LocalizationService.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Localization;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
-using MediaBrowser.Server.Implementations.HttpServer;
using MoreLinq;
using ServiceStack.ServiceHost;
using System.Collections.Generic;
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 0ea6851f56..a46fe06012 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -39,36 +39,13 @@
..\packages\morelinq.1.0.15631-beta\lib\net35\MoreLinq.dll
-
- False
- ..\packages\ServiceStack.3.9.42\lib\net35\ServiceStack.dll
-
-
- False
+
..\packages\ServiceStack.Common.3.9.42\lib\net35\ServiceStack.Common.dll
-
- False
+
..\packages\ServiceStack.Common.3.9.42\lib\net35\ServiceStack.Interfaces.dll
-
- False
- ..\packages\ServiceStack.OrmLite.SqlServer.3.9.42\lib\ServiceStack.OrmLite.dll
-
-
- False
- ..\packages\ServiceStack.OrmLite.SqlServer.3.9.42\lib\ServiceStack.OrmLite.SqlServer.dll
-
-
- False
- ..\packages\ServiceStack.Redis.3.9.42\lib\net35\ServiceStack.Redis.dll
-
-
- False
- ..\packages\ServiceStack.3.9.42\lib\net35\ServiceStack.ServiceInterface.dll
-
-
- False
+
..\packages\ServiceStack.Text.3.9.42\lib\net35\ServiceStack.Text.dll
@@ -133,10 +110,6 @@
{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}
MediaBrowser.Model
-
- {2e781478-814d-4a48-9d80-bff206441a65}
- MediaBrowser.Server.Implementations
-
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index a741eff410..742e26bc06 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -2,7 +2,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Updates;
using MediaBrowser.Model.Updates;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
@@ -16,7 +15,7 @@ namespace MediaBrowser.Api
/// Class GetPackage
///
[Route("/Packages/{Name}", "GET")]
- [ServiceStack.ServiceHost.Api(("Gets a package, by name"))]
+ [Api(("Gets a package, by name"))]
public class GetPackage : IReturn
{
///
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 1740ad2eba..6ec59c9de9 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -6,7 +6,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Server.Implementations.HttpServer;
using System;
using System.Collections.Generic;
using System.ComponentModel;
diff --git a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs
index ea1c8d3012..a540349f06 100644
--- a/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/AudioHlsService.cs
@@ -44,7 +44,7 @@ namespace MediaBrowser.Api.Playback.Hls
file = Path.Combine(ApplicationPaths.EncodedMediaCachePath, file);
- return ToStaticFileResult(file);
+ return ResultFactory.GetStaticFileResult(RequestContext, file);
}
///
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 578c4a9f19..9112ee3553 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using System.Collections.Generic;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Library;
@@ -86,8 +87,7 @@ namespace MediaBrowser.Api.Playback.Hls
try
{
- Response.ContentType = MimeTypes.GetMimeType("playlist.m3u8");
- return playlistText;
+ return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary());
}
finally
{
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index 050391e813..dfcc3a2c59 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -36,7 +36,7 @@ namespace MediaBrowser.Api.Playback.Hls
file = Path.Combine(ApplicationPaths.EncodedMediaCachePath, file);
- return ToStaticFileResult(file);
+ return ResultFactory.GetStaticFileResult(RequestContext, file);
}
///
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index 90c233e90b..3773a2a1c5 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -1,11 +1,12 @@
-using System;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
+using System;
+using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@@ -16,7 +17,7 @@ namespace MediaBrowser.Api.Playback.Progressive
///
public abstract class BaseProgressiveStreamingService : BaseStreamingService
{
- protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager) :
+ protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager) :
base(appPaths, userManager, libraryManager, isoManager)
{
}
@@ -85,18 +86,21 @@ namespace MediaBrowser.Api.Playback.Progressive
///
/// Adds the dlna headers.
///
- private bool AddDlnaHeaders(StreamState state)
+ /// The state.
+ /// The response headers.
+ /// true if XXXX, false otherwise
+ private void AddDlnaHeaders(StreamState state, IDictionary responseHeaders)
{
var timeSeek = RequestContext.GetHeader("TimeSeekRange.dlna.org");
if (!string.IsNullOrEmpty(timeSeek))
{
- Response.StatusCode = 406;
- return false;
+ ResultFactory.ThrowError(406, "Time seek not supported during encoding.", responseHeaders);
+ return;
}
var transferMode = RequestContext.GetHeader("transferMode.dlna.org");
- Response.AddHeader("transferMode.dlna.org", string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode);
+ responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
var contentFeatures = string.Empty;
var extension = GetOutputFileExtension(state);
@@ -140,10 +144,8 @@ namespace MediaBrowser.Api.Playback.Progressive
if (!string.IsNullOrEmpty(contentFeatures))
{
- Response.AddHeader("ContentFeatures.DLNA.ORG", contentFeatures);
+ responseHeaders["ContentFeatures.DLNA.ORG"] = contentFeatures;
}
-
- return true;
}
///
@@ -165,45 +167,45 @@ namespace MediaBrowser.Api.Playback.Progressive
{
var state = GetState(request);
- if (!AddDlnaHeaders(state))
- {
- return null;
- }
+ var responseHeaders = new Dictionary();
+
+ AddDlnaHeaders(state, responseHeaders);
if (request.Static)
{
- return ToStaticFileResult(state.Item.Path, isHeadRequest);
+ return ResultFactory.GetStaticFileResult(RequestContext, state.Item.Path, responseHeaders, isHeadRequest);
}
var outputPath = GetOutputFilePath(state);
if (File.Exists(outputPath) && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive))
{
- return ToStaticFileResult(outputPath, isHeadRequest);
+ return ResultFactory.GetStaticFileResult(RequestContext, outputPath, responseHeaders, isHeadRequest);
}
- Response.AddHeader("Accept-Ranges", "none");
-
- return GetStreamResult(state, isHeadRequest).Result;
+ return GetStreamResult(state, responseHeaders, isHeadRequest).Result;
}
///
/// Gets the stream result.
///
/// The state.
+ /// The response headers.
/// if set to true [is head request].
/// Task{System.Object}.
- private async Task GetStreamResult(StreamState state, bool isHeadRequest)
+ private async Task
[Route("/Plugins/{Id}/Assembly", "GET")]
- [ServiceStack.ServiceHost.Api(("Gets a plugin assembly file"))]
+ [Api(("Gets a plugin assembly file"))]
public class GetPluginAssembly
{
///
@@ -58,7 +57,7 @@ namespace MediaBrowser.Api
/// Class GetPluginConfiguration
///
[Route("/Plugins/{Id}/Configuration", "GET")]
- [ServiceStack.ServiceHost.Api(("Gets a plugin's configuration"))]
+ [Api(("Gets a plugin's configuration"))]
public class GetPluginConfiguration
{
///
@@ -73,7 +72,7 @@ namespace MediaBrowser.Api
/// Class UpdatePluginConfiguration
///
[Route("/Plugins/{Id}/Configuration", "POST")]
- [ServiceStack.ServiceHost.Api(("Updates a plugin's configuration"))]
+ [Api(("Updates a plugin's configuration"))]
public class UpdatePluginConfiguration : IRequiresRequestStream, IReturnVoid
{
///
@@ -94,7 +93,7 @@ namespace MediaBrowser.Api
/// Class GetPluginConfigurationFile
///
[Route("/Plugins/{Id}/ConfigurationFile", "GET")]
- [ServiceStack.ServiceHost.Api(("Gets a plugin's configuration file, in plain text"))]
+ [Api(("Gets a plugin's configuration file, in plain text"))]
public class GetPluginConfigurationFile
{
///
@@ -109,7 +108,8 @@ namespace MediaBrowser.Api
/// Class GetPluginSecurityInfo
///
[Route("/Plugins/SecurityInfo", "GET")]
- [ServiceStack.ServiceHost.Api(("Gets plugin registration information"))]
+ [Api(("Gets plugin registration information"))]
+ [Restrict(VisibilityTo = EndpointAttributes.None)]
public class GetPluginSecurityInfo : IReturn
{
}
@@ -118,7 +118,8 @@ namespace MediaBrowser.Api
/// Class UpdatePluginSecurityInfo
///
[Route("/Plugins/SecurityInfo", "POST")]
- [ServiceStack.ServiceHost.Api(("Updates plugin registration information"))]
+ [Api("Updates plugin registration information")]
+ [Restrict(VisibilityTo = EndpointAttributes.None)]
public class UpdatePluginSecurityInfo : PluginSecurityInfo, IReturnVoid
{
}
@@ -171,7 +172,7 @@ namespace MediaBrowser.Api
public object Get(GetPlugins request)
{
var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToList();
-
+
return ToOptimizedResult(result);
}
@@ -184,7 +185,7 @@ namespace MediaBrowser.Api
{
var plugin = _appHost.Plugins.First(p => p.Id == request.Id);
- return ToStaticFileResult(plugin.AssemblyFilePath);
+ return ResultFactory.GetStaticFileResult(RequestContext, plugin.AssemblyFilePath);
}
///
@@ -212,7 +213,7 @@ namespace MediaBrowser.Api
{
var plugin = _appHost.Plugins.First(p => p.Id == request.Id);
- return ToStaticFileResult(plugin.ConfigurationFilePath);
+ return ResultFactory.GetStaticFileResult(RequestContext, plugin.ConfigurationFilePath);
}
///
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
index 8716899f41..e31d4b454a 100644
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
+++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Model.Tasks;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using System;
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index 09796c67f1..66822d8528 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -2,7 +2,6 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
@@ -15,7 +14,7 @@ namespace MediaBrowser.Api.UserLibrary
/// Class GetItems
///
[Route("/Users/{UserId}/Items", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets items based on a query.")]
+ [Api(Description = "Gets items based on a query.")]
public class GetItems : BaseItemsRequest, IReturn
{
///
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index 4e32204e95..b495d07f96 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -2,7 +2,6 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Serialization;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using System;
diff --git a/MediaBrowser.Api/WeatherService.cs b/MediaBrowser.Api/WeatherService.cs
index 2b1eb53b74..25f6d237a8 100644
--- a/MediaBrowser.Api/WeatherService.cs
+++ b/MediaBrowser.Api/WeatherService.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Controller;
using MediaBrowser.Model.Weather;
-using MediaBrowser.Server.Implementations.HttpServer;
using ServiceStack.ServiceHost;
using System.Linq;
using System.Threading;
@@ -11,7 +10,7 @@ namespace MediaBrowser.Api
/// Class Weather
///
[Route("/Weather", "GET")]
- [ServiceStack.ServiceHost.Api(Description = "Gets weather information for a given location")]
+ [Api(Description = "Gets weather information for a given location")]
public class GetWeather : IReturn
{
///
diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config
index acab67a837..b45320b0e3 100644
--- a/MediaBrowser.Api/packages.config
+++ b/MediaBrowser.Api/packages.config
@@ -1,9 +1,6 @@
-
-
-
\ No newline at end of file
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index bc0d79e454..76bf63e3a5 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -38,6 +38,15 @@
+
+ ..\packages\ServiceStack.Common.3.9.42\lib\net35\ServiceStack.Common.dll
+
+
+ ..\packages\ServiceStack.Common.3.9.42\lib\net35\ServiceStack.Interfaces.dll
+
+
+ ..\packages\ServiceStack.Text.3.9.42\lib\net35\ServiceStack.Text.dll
+
@@ -62,6 +71,7 @@
+
@@ -75,7 +85,6 @@
-
@@ -107,6 +116,7 @@
+
diff --git a/MediaBrowser.Common/Net/IHasResultFactory.cs b/MediaBrowser.Common/Net/IHasResultFactory.cs
new file mode 100644
index 0000000000..d9da0c7e4e
--- /dev/null
+++ b/MediaBrowser.Common/Net/IHasResultFactory.cs
@@ -0,0 +1,17 @@
+using ServiceStack.ServiceHost;
+
+namespace MediaBrowser.Common.Net
+{
+ ///
+ /// Interface IHasResultFactory
+ /// Services that require a ResultFactory should implement this
+ ///
+ public interface IHasResultFactory : IRequiresRequestContext
+ {
+ ///
+ /// Gets or sets the result factory.
+ ///
+ /// The result factory.
+ IHttpResultFactory ResultFactory { get; set; }
+ }
+}
diff --git a/MediaBrowser.Common/Net/IHttpResultFactory.cs b/MediaBrowser.Common/Net/IHttpResultFactory.cs
index 565a2dce9c..55c0e5b9b3 100644
--- a/MediaBrowser.Common/Net/IHttpResultFactory.cs
+++ b/MediaBrowser.Common/Net/IHttpResultFactory.cs
@@ -1,9 +1,97 @@
-using System.IO;
+using ServiceStack.ServiceHost;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
namespace MediaBrowser.Common.Net
{
+ ///
+ /// Interface IHttpResultFactory
+ ///
public interface IHttpResultFactory
{
- object GetResult(Stream stream, string contentType);
+ ///
+ /// Throws the error.
+ ///
+ /// The status code.
+ /// The error message.
+ /// The response headers.
+ void ThrowError(int statusCode, string errorMessage, IDictionary responseHeaders = null);
+
+ ///
+ /// Gets the result.
+ ///
+ /// The content.
+ /// Type of the content.
+ /// The response headers.
+ /// System.Object.
+ object GetResult(object content, string contentType, IDictionary responseHeaders = null);
+
+ ///
+ /// Gets the optimized result.
+ ///
+ ///
+ /// The request context.
+ /// The result.
+ /// The response headers.
+ /// System.Object.
+ object GetOptimizedResult(IRequestContext requestContext, T result, IDictionary responseHeaders = null)
+ where T : class;
+
+ ///
+ /// Gets the optimized result using cache.
+ ///
+ ///
+ /// The request context.
+ /// The cache key.
+ /// The last date modified.
+ /// Duration of the cache.
+ /// The factory function that creates the response object.
+ /// The response headers.
+ /// System.Object.
+ object GetOptimizedResultUsingCache(IRequestContext requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func factoryFn, IDictionary responseHeaders = null)
+ where T : class;
+
+ ///
+ /// Gets the cached result.
+ ///
+ ///
+ /// The request context.
+ /// The cache key.
+ /// The last date modified.
+ /// Duration of the cache.
+ /// The factory fn.
+ /// Type of the content.
+ /// The response headers.
+ /// System.Object.
+ object GetCachedResult(IRequestContext requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func factoryFn, string contentType, IDictionary responseHeaders = null)
+ where T : class;
+
+ ///
+ /// Gets the static result.
+ ///
+ /// The request context.
+ /// The cache key.
+ /// The last date modified.
+ /// Duration of the cache.
+ /// Type of the content.
+ /// The factory fn.
+ /// The response headers.
+ /// if set to true [is head request].
+ /// System.Object.
+ object GetStaticResult(IRequestContext requestContext, Guid cacheKey, DateTime? lastDateModified,
+ TimeSpan? cacheDuration, string contentType, Func> factoryFn,
+ IDictionary responseHeaders = null, bool isHeadRequest = false);
+
+ ///
+ /// Gets the static file result.
+ ///
+ /// The request context.
+ /// The path.
+ /// The response headers.
+ /// if set to true [is head request].
+ /// System.Object.
+ object GetStaticFileResult(IRequestContext requestContext, string path, IDictionary responseHeaders = null, bool isHeadRequest = false);
}
}
diff --git a/MediaBrowser.Common/Net/IRestfulService.cs b/MediaBrowser.Common/Net/IRestfulService.cs
index 9f37676450..7a1b267951 100644
--- a/MediaBrowser.Common/Net/IRestfulService.cs
+++ b/MediaBrowser.Common/Net/IRestfulService.cs
@@ -1,16 +1,11 @@
-using System.Collections.Generic;
+using ServiceStack.ServiceHost;
namespace MediaBrowser.Common.Net
{
///
/// Interface IRestfulService
///
- public interface IRestfulService
+ public interface IRestfulService : IService
{
- ///
- /// Gets the routes.
- ///
- /// IEnumerable{RouteInfo}.
- IEnumerable GetRoutes();
}
}
diff --git a/MediaBrowser.Common/Net/RouteInfo.cs b/MediaBrowser.Common/Net/RouteInfo.cs
deleted file mode 100644
index 379aff9c5e..0000000000
--- a/MediaBrowser.Common/Net/RouteInfo.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-
-namespace MediaBrowser.Common.Net
-{
- ///
- /// Class RouteInfo
- ///
- public class RouteInfo
- {
- ///
- /// Gets or sets the path.
- ///
- /// The path.
- public string Path { get; set; }
-
- ///
- /// Gets or sets the verbs.
- ///
- /// The verbs.
- public string Verbs { get; set; }
-
- ///
- /// Gets or sets the type of the request.
- ///
- /// The type of the request.
- public Type RequestType { get; set; }
- }
-}
diff --git a/MediaBrowser.Common/packages.config b/MediaBrowser.Common/packages.config
new file mode 100644
index 0000000000..46c46de10d
--- /dev/null
+++ b/MediaBrowser.Common/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/HttpServer/BaseRestService.cs b/MediaBrowser.Server.Implementations/HttpServer/BaseRestService.cs
deleted file mode 100644
index ff22737501..0000000000
--- a/MediaBrowser.Server.Implementations/HttpServer/BaseRestService.cs
+++ /dev/null
@@ -1,470 +0,0 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using ServiceStack.Common;
-using ServiceStack.Common.Web;
-using ServiceStack.ServiceHost;
-using ServiceStack.ServiceInterface;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Net;
-using System.Threading.Tasks;
-using MimeTypes = MediaBrowser.Common.Net.MimeTypes;
-
-namespace MediaBrowser.Server.Implementations.HttpServer
-{
- ///
- /// Class BaseRestService
- ///
- public class BaseRestService : Service, IRestfulService
- {
- ///
- /// Gets or sets the logger.
- ///
- /// The logger.
- public ILogger Logger { get; set; }
-
- ///
- /// Gets a value indicating whether this instance is range request.
- ///
- /// true if this instance is range request; otherwise, false.
- protected bool IsRangeRequest
- {
- get
- {
- return !string.IsNullOrEmpty(RequestContext.GetHeader("Range"));
- }
- }
-
- ///
- /// To the optimized result.
- ///
- ///
- /// The result.
- /// System.Object.
- /// result
- protected object ToOptimizedResult(T result)
- where T : class
- {
- if (result == null)
- {
- throw new ArgumentNullException("result");
- }
-
- return RequestContext.ToOptimizedResult(result);
- }
-
- ///
- /// To the optimized result using cache.
- ///
- ///
- /// The cache key.
- /// The last date modified.
- /// Duration of the cache.
- /// The factory fn.
- /// System.Object.
- /// cacheKey
- protected object ToOptimizedResultUsingCache(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func factoryFn)
- where T : class
- {
- if (cacheKey == Guid.Empty)
- {
- throw new ArgumentNullException("cacheKey");
- }
- if (factoryFn == null)
- {
- throw new ArgumentNullException("factoryFn");
- }
-
- var key = cacheKey.ToString("N");
-
- var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration);
-
- if (result != null)
- {
- // Return null so that service stack won't do anything
- return null;
- }
-
- return ToOptimizedResult(factoryFn());
- }
-
- ///
- /// To the cached result.
- ///
- ///
- /// The cache key.
- /// The last date modified.
- /// Duration of the cache.
- /// The factory fn.
- /// Type of the content.
- /// System.Object.
- /// cacheKey
- protected object ToCachedResult(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func factoryFn, string contentType)
- where T : class
- {
- if (cacheKey == Guid.Empty)
- {
- throw new ArgumentNullException("cacheKey");
- }
- if (factoryFn == null)
- {
- throw new ArgumentNullException("factoryFn");
- }
-
- Response.ContentType = contentType;
-
- var key = cacheKey.ToString("N");
-
- var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration);
-
- if (result != null)
- {
- // Return null so that service stack won't do anything
- return null;
- }
-
- return factoryFn();
- }
-
- ///
- /// To the static file result.
- ///
- /// The path.
- /// if set to true [headers only].
- /// System.Object.
- /// path
- protected object ToStaticFileResult(string path, bool headersOnly = false)
- {
- if (string.IsNullOrEmpty(path))
- {
- throw new ArgumentNullException("path");
- }
-
- var dateModified = File.GetLastWriteTimeUtc(path);
-
- var cacheKey = path + dateModified.Ticks;
-
- return ToStaticResult(cacheKey.GetMD5(), dateModified, null, MimeTypes.GetMimeType(path), () => Task.FromResult(GetFileStream(path)), headersOnly);
- }
-
- ///
- /// Gets the file stream.
- ///
- /// The path.
- /// Stream.
- private Stream GetFileStream(string path)
- {
- return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
- }
-
- ///
- /// To the static result.
- ///
- /// The cache key.
- /// The last date modified.
- /// Duration of the cache.
- /// Type of the content.
- /// The factory fn.
- /// if set to true [headers only].
- /// System.Object.
- /// cacheKey
- protected object ToStaticResult(Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType, Func> factoryFn, bool headersOnly = false)
- {
- if (cacheKey == Guid.Empty)
- {
- throw new ArgumentNullException("cacheKey");
- }
- if (factoryFn == null)
- {
- throw new ArgumentNullException("factoryFn");
- }
-
- var key = cacheKey.ToString("N");
-
- Response.ContentType = contentType;
-
- var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration);
-
- if (result != null)
- {
- // Return null so that service stack won't do anything
- return null;
- }
-
- var compress = ShouldCompressResponse(contentType);
-
- return ToStaticResult(contentType, factoryFn, compress, headersOnly).Result;
- }
-
- ///
- /// Shoulds the compress response.
- ///
- /// Type of the content.
- /// true if XXXX, false otherwise
- private bool ShouldCompressResponse(string contentType)
- {
- // It will take some work to support compression with byte range requests
- if (IsRangeRequest)
- {
- return false;
- }
-
- // Don't compress media
- if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
-
- // Don't compress images
- if (contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
-
- if (contentType.StartsWith("font/", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
- if (contentType.StartsWith("application/", StringComparison.OrdinalIgnoreCase))
- {
- return false;
- }
-
- return true;
- }
-
- ///
- /// To the static result.
- ///
- /// Type of the content.
- /// The factory fn.
- /// if set to true [compress].
- /// if set to true [headers only].
- /// System.Object.
- private async Task
[Export(typeof(IRestfulService))]
- public class DashboardService : BaseRestService
+ public class DashboardService : IRestfulService, IHasResultFactory
{
+ ///
+ /// Gets or sets the logger.
+ ///
+ /// The logger.
+ public ILogger Logger { get; set; }
+
+ ///
+ /// Gets or sets the HTTP result factory.
+ ///
+ /// The HTTP result factory.
+ public IHttpResultFactory ResultFactory { get; set; }
+
+ ///
+ /// Gets or sets the request context.
+ ///
+ /// The request context.
+ public IRequestContext RequestContext { get; set; }
+
///
/// Gets or sets the task manager.
///
@@ -172,7 +193,7 @@ namespace MediaBrowser.WebDashboard.Api
{
var page = ServerEntryPoint.Instance.PluginConfigurationPages.First(p => p.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
- return ToStaticResult(page.Plugin.Version.ToString().GetMD5(), page.Plugin.AssemblyDateLastModified, null, MimeTypes.GetMimeType("page.html"), () => ModifyHtml(page.GetHtmlStream()));
+ return ResultFactory.GetStaticResult(RequestContext, page.Plugin.Version.ToString().GetMD5(), page.Plugin.AssemblyDateLastModified, null, MimeTypes.GetMimeType("page.html"), () => ModifyHtml(page.GetHtmlStream()));
}
///
@@ -189,7 +210,7 @@ namespace MediaBrowser.WebDashboard.Api
pages = pages.Where(p => p.ConfigurationPageType == request.PageType.Value);
}
- return ToOptimizedResult(pages.Select(p => new ConfigurationPageInfo(p)).ToList());
+ return ResultFactory.GetOptimizedResult(RequestContext, pages.Select(p => new ConfigurationPageInfo(p)).ToList());
}
///
@@ -207,8 +228,7 @@ namespace MediaBrowser.WebDashboard.Api
// But always cache images to simulate production
if (!_serverConfigurationManager.Configuration.EnableDashboardResponseCaching && !contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
{
- Response.ContentType = contentType;
- return GetResourceStream(path).Result;
+ return ResultFactory.GetResult(GetResourceStream(path).Result, contentType);
}
TimeSpan? cacheDuration = null;
@@ -224,7 +244,7 @@ namespace MediaBrowser.WebDashboard.Api
var cacheKey = (assembly.Version + path).GetMD5();
- return ToStaticResult(cacheKey, null, cacheDuration, contentType, () => GetResourceStream(path));
+ return ResultFactory.GetStaticResult(RequestContext, cacheKey, null, cacheDuration, contentType, () => GetResourceStream(path));
}
///
@@ -385,6 +405,7 @@ namespace MediaBrowser.WebDashboard.Api
var files = new[]
{
"http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.css",
+ "http://vjs.zencdn.net/c/video-js.css",
"thirdparty/jqm-icon-pack-3.0/font-awesome/jqm-icon-pack-3.0.0-fa.css",
"css/site.css" + versionString
};
@@ -407,6 +428,7 @@ namespace MediaBrowser.WebDashboard.Api
{
"http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js",
"http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js",
+ "http://vjs.zencdn.net/c/video.js",
"scripts/all.js" + versionString
};
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 6fcb1d2e63..843fd7a723 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -35,10 +35,6 @@
Always
-
- False
- ..\packages\ServiceStack.3.9.42\lib\net35\ServiceStack.dll
-
False
..\packages\ServiceStack.Common.3.9.42\lib\net35\ServiceStack.Common.dll
@@ -47,22 +43,6 @@
False
..\packages\ServiceStack.Common.3.9.42\lib\net35\ServiceStack.Interfaces.dll
-
- False
- ..\packages\ServiceStack.OrmLite.SqlServer.3.9.42\lib\ServiceStack.OrmLite.dll
-
-
- False
- ..\packages\ServiceStack.OrmLite.SqlServer.3.9.42\lib\ServiceStack.OrmLite.SqlServer.dll
-
-
- False
- ..\packages\ServiceStack.Redis.3.9.42\lib\net35\ServiceStack.Redis.dll
-
-
- False
- ..\packages\ServiceStack.3.9.42\lib\net35\ServiceStack.ServiceInterface.dll
-
False
..\packages\ServiceStack.Text.3.9.42\lib\net35\ServiceStack.Text.dll
@@ -101,10 +81,6 @@
{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}
MediaBrowser.Model
-
- {2e781478-814d-4a48-9d80-bff206441a65}
- MediaBrowser.Server.Implementations
-
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index c9f456705f..4e1ee3bff0 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,9 +1,6 @@
-
-
-
\ No newline at end of file