diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations/HttpServer')
8 files changed, 86 insertions, 155 deletions
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 1cec4461b..16ca8b099 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -14,6 +14,7 @@ using ServiceStack.Host.HttpListener; using ServiceStack.Logging; using ServiceStack.Web; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -39,13 +40,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected; + private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); + /// <summary> /// Gets the local end points. /// </summary> /// <value>The local end points.</value> public IEnumerable<string> LocalEndPoints { - get { return _listener == null ? new List<string>() : _listener.LocalEndPoints; } + get { return _listener == null ? new List<string>() : _localEndPoints.Keys.ToList(); } } public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices) @@ -151,6 +154,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer return this; } + private void OnRequestReceived(string localEndPoint) + { + _localEndPoints.GetOrAdd(localEndPoint, localEndPoint); + } + /// <summary> /// Starts the Web Service /// </summary> @@ -159,9 +167,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); _listener = NativeWebSocket.IsSupported - ? _listener = new HttpListenerServer(_logger) + ? _listener = new HttpListenerServer(_logger, OnRequestReceived) //? _listener = new WebSocketSharpListener(_logger) - : _listener = new WebSocketSharpListener(_logger); + : _listener = new WebSocketSharpListener(_logger, OnRequestReceived); _listener.WebSocketHandler = WebSocketHandler; _listener.ErrorHandler = ErrorHandler; diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index be3e5f005..9997cfbdb 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -289,41 +289,28 @@ namespace MediaBrowser.Server.Implementations.HttpServer return null; } - /// <summary> - /// Gets the static file result. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="path">The path.</param> - /// <param name="fileShare">The file share.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - /// <returns>System.Object.</returns> - /// <exception cref="ArgumentNullException">path</exception> - /// <exception cref="System.ArgumentNullException">path</exception> public object GetStaticFileResult(IRequest requestContext, string path, - FileShare fileShare = FileShare.Read, - IDictionary<string, string> responseHeaders = null, - bool isHeadRequest = false) + FileShare fileShare = FileShare.Read) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } - return GetStaticFileResult(requestContext, path, MimeTypes.GetMimeType(path), null, fileShare, responseHeaders, isHeadRequest); + return GetStaticFileResult(requestContext, new StaticFileResultOptions + { + Path = path, + FileShare = fileShare + }); } public object GetStaticFileResult(IRequest requestContext, - string path, - string contentType, - TimeSpan? cacheCuration = null, - FileShare fileShare = FileShare.Read, - IDictionary<string, string> responseHeaders = null, - bool isHeadRequest = false, - bool throttle = false, - long throttleLimit = 0) + StaticFileResultOptions options) { + var path = options.Path; + var fileShare = options.FileShare; + if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); @@ -334,11 +321,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer throw new ArgumentException("FileShare must be either Read or ReadWrite"); } - var dateModified = _fileSystem.GetLastWriteTimeUtc(path); + if (string.IsNullOrWhiteSpace(options.ContentType)) + { + options.ContentType = MimeTypes.GetMimeType(path); + } - var cacheKey = path + dateModified.Ticks; + options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path); + var cacheKey = path + options.DateLastModified.Value.Ticks; - return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, cacheCuration, contentType, () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest, throttle, throttleLimit); + options.CacheKey = cacheKey.GetMD5(); + options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare)); + + return GetStaticResult(requestContext, options); } /// <summary> @@ -352,21 +346,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer return _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, fileShare, true); } - /// <summary> - /// Gets the static result. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">cacheKey - /// or - /// factoryFn</exception> public object GetStaticResult(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, @@ -376,39 +355,37 @@ namespace MediaBrowser.Server.Implementations.HttpServer IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false) { - return GetStaticResult(requestContext, cacheKey, lastDateModified, cacheDuration, contentType, factoryFn, - responseHeaders, isHeadRequest, false, 0); + return GetStaticResult(requestContext, new StaticResultOptions + { + CacheDuration = cacheDuration, + CacheKey = cacheKey, + ContentFactory = factoryFn, + ContentType = contentType, + DateLastModified = lastDateModified, + IsHeadRequest = isHeadRequest, + ResponseHeaders = responseHeaders + }); } - public object GetStaticResult(IRequest requestContext, - Guid cacheKey, - DateTime? lastDateModified, - TimeSpan? cacheDuration, - string contentType, - Func<Task<Stream>> factoryFn, - IDictionary<string, string> responseHeaders = null, - bool isHeadRequest = false, - bool throttle = false, - long throttleLimit = 0) + public object GetStaticResult(IRequest requestContext, StaticResultOptions options) { + var cacheKey = options.CacheKey; + options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(); + var contentType = options.ContentType; + if (cacheKey == Guid.Empty) { throw new ArgumentNullException("cacheKey"); } - if (factoryFn == null) + if (options.ContentFactory == null) { throw new ArgumentNullException("factoryFn"); } var key = cacheKey.ToString("N"); - if (responseHeaders == null) - { - responseHeaders = new Dictionary<string, string>(); - } - // See if the result is already cached in the browser - var result = GetCachedResult(requestContext, responseHeaders, cacheKey, key, lastDateModified, cacheDuration, contentType); + var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType); if (result != null) { @@ -416,8 +393,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer } var compress = ShouldCompressResponse(requestContext, contentType); - var hasOptions = GetStaticResult(requestContext, responseHeaders, contentType, factoryFn, compress, isHeadRequest, throttle, throttleLimit).Result; - AddResponseHeaders(hasOptions, responseHeaders); + var hasOptions = GetStaticResult(requestContext, options, compress).Result; + AddResponseHeaders(hasOptions, options.ResponseHeaders); return hasOptions; } @@ -473,20 +450,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// </summary> private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - /// <summary> - /// Gets the static result. - /// </summary> - /// <param name="requestContext">The request context.</param> - /// <param name="responseHeaders">The response headers.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="compress">if set to <c>true</c> [compress].</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - /// <param name="throttle">if set to <c>true</c> [throttle].</param> - /// <param name="throttleLimit">The throttle limit.</param> - /// <returns>Task{IHasOptions}.</returns> - private async Task<IHasOptions> GetStaticResult(IRequest requestContext, IDictionary<string, string> responseHeaders, string contentType, Func<Task<Stream>> factoryFn, bool compress, bool isHeadRequest, bool throttle, long throttleLimit = 0) + private async Task<IHasOptions> GetStaticResult(IRequest requestContext, StaticResultOptions options, bool compress) { + var isHeadRequest = options.IsHeadRequest; + var factoryFn = options.ContentFactory; + var contentType = options.ContentType; + var responseHeaders = options.ResponseHeaders; + var requestedCompressionType = requestContext.GetCompressionType(); if (!compress || string.IsNullOrEmpty(requestedCompressionType)) @@ -499,8 +469,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer { return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest) { - Throttle = throttle, - ThrottleLimit = throttleLimit + Throttle = options.Throttle, + ThrottleLimit = options.ThrottleLimit, + MinThrottlePosition = options.MinThrottlePosition }; } @@ -515,8 +486,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer return new StreamWriter(stream, contentType, _logger) { - Throttle = throttle, - ThrottleLimit = throttleLimit + Throttle = options.Throttle, + ThrottleLimit = options.ThrottleLimit, + MinThrottlePosition = options.MinThrottlePosition }; } @@ -746,14 +718,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer throw error; } - - public object GetOptimizedSerializedResultUsingCache<T>(IRequest request, T result) - where T : class - { - var json = _jsonSerializer.SerializeToString(result); - var cacheKey = json.GetMD5(); - - return GetOptimizedResultUsingCache(request, cacheKey, null, null, () => result); - } } }
\ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs index 1d80a263c..86e8856cf 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs @@ -8,8 +8,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer { public interface IHttpListener : IDisposable { - IEnumerable<string> LocalEndPoints { get; } - /// <summary> /// Gets or sets the error handler. /// </summary> diff --git a/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs index bdc2750fb..118bec60e 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs @@ -4,7 +4,6 @@ using ServiceStack; using ServiceStack.Host.HttpListener; using ServiceStack.Web; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; @@ -20,26 +19,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer.NetListener private HttpListener _listener; private readonly AutoResetEvent _listenForNextRequest = new AutoResetEvent(false); - public System.Action<Exception, IRequest> ErrorHandler { get; set; } + public Action<Exception, IRequest> ErrorHandler { get; set; } public Action<WebSocketConnectEventArgs> WebSocketHandler { get; set; } - public System.Func<IHttpRequest, Uri, Task> RequestHandler { get; set; } + public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; } - private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); + private readonly Action<string> _endpointListener; - public HttpListenerServer(ILogger logger) + public HttpListenerServer(ILogger logger, Action<string> endpointListener) { _logger = logger; + _endpointListener = endpointListener; } - /// <summary> - /// Gets the local end points. - /// </summary> - /// <value>The local end points.</value> - public IEnumerable<string> LocalEndPoints - { - get { return _localEndPoints.Keys.ToList(); } - } - private List<string> UrlPrefixes { get; set; } public void Start(IEnumerable<string> urlPrefixes) @@ -47,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.NetListener UrlPrefixes = urlPrefixes.ToList(); if (_listener == null) - _listener = new System.Net.HttpListener(); + _listener = new HttpListener(); //HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First()); @@ -229,7 +220,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.NetListener { var address = endpoint.ToString(); - _localEndPoints.GetOrAdd(address, address); + _endpointListener(address); } LogRequest(_logger, request); diff --git a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs index 5fd43aa76..657545069 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs @@ -26,6 +26,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer public bool Throttle { get; set; } public long ThrottleLimit { get; set; } + public long MinThrottlePosition; /// <summary> /// The _options @@ -166,7 +167,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer { responseStream = new ThrottledStream(responseStream, ThrottleLimit) { - MinThrottlePosition = ThrottleLimit * 180 + MinThrottlePosition = MinThrottlePosition }; } var task = WriteToAsync(responseStream); diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs index 19870c435..2b9ae7d09 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security /// </summary> public string HtmlRedirect { get; set; } - public void Authenticate(IRequest req, IResponse res, object requestDto) + public void Authenticate(IRequest req, IResponse res, object requestDto, bool allowLocal) { if (HostContext.HasValidAuthSecret(req)) return; @@ -50,13 +50,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security //ExecuteBasic(req, res, requestDto); //first check if session is authenticated //if (res.IsClosed) return; //AuthenticateAttribute already closed the request (ie auth failed) - ValidateUser(req); + ValidateUser(req, allowLocal); } // TODO: Remove this when all clients have supported the new sescurity - private readonly List<string> _updatedClients = new List<string>(){"Dashboard"}; + private readonly List<string> _updatedClients = new List<string>() { "Dashboard", "Chromecast" }; - private void ValidateUser(IRequest req) + private void ValidateUser(IRequest req, bool allowLocal) { //This code is executed before the service var auth = AuthorizationContext.GetAuthorizationInfo(req); @@ -65,7 +65,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security || _config.Configuration.EnableTokenAuthentication || _updatedClients.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { - SessionManager.ValidateSecurityToken(auth.Token); + if (!allowLocal || !req.IsLocal) + { + SessionManager.ValidateSecurityToken(auth.Token); + } } var user = string.IsNullOrWhiteSpace(auth.UserId) @@ -96,35 +99,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security } } - private void ExecuteBasic(IRequest req, IResponse res, object requestDto) - { - if (AuthenticateService.AuthProviders == null) - throw new InvalidOperationException( - "The AuthService must be initialized by calling AuthService.Init to use an authenticate attribute"); - - var matchingOAuthConfigs = AuthenticateService.AuthProviders.Where(x => - this.Provider.IsNullOrEmpty() - || x.Provider == this.Provider).ToList(); - - if (matchingOAuthConfigs.Count == 0) - { - res.WriteError(req, requestDto, "No OAuth Configs found matching {0} provider" - .Fmt(this.Provider ?? "any")); - res.EndRequest(); - } - - matchingOAuthConfigs.OfType<IAuthWithRequest>() - .Each(x => x.PreAuthenticate(req, res)); - - var session = req.GetSession(); - if (session == null || !matchingOAuthConfigs.Any(x => session.IsAuthorized(x.Provider))) - { - if (this.DoHtmlRedirectIfConfigured(req, res, true)) return; - - AuthProvider.HandleFailedAuth(matchingOAuthConfigs[0], session, req, res); - } - } - protected bool DoHtmlRedirectIfConfigured(IRequest req, IResponse res, bool includeRedirectParam = false) { var htmlRedirect = this.HtmlRedirect ?? AuthenticateService.HtmlRedirect; diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index 477aa3878..f2fae9e90 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -3,7 +3,6 @@ using MediaBrowser.Model.Logging; using ServiceStack; using ServiceStack.Web; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; @@ -15,20 +14,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { public class WebSocketSharpListener : IHttpListener { - private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase); private WebSocketSharp.Net.HttpListener _listener; private readonly AutoResetEvent _listenForNextRequest = new AutoResetEvent(false); private readonly ILogger _logger; + private readonly Action<string> _endpointListener; - public WebSocketSharpListener(ILogger logger) + public WebSocketSharpListener(ILogger logger, Action<string> endpointListener) { _logger = logger; - } - - public IEnumerable<string> LocalEndPoints - { - get { return _localEndPoints.Keys.ToList(); } + _endpointListener = endpointListener; } public Action<Exception, IRequest> ErrorHandler { get; set; } @@ -170,7 +165,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { var address = endpoint.ToString(); - _localEndPoints.GetOrAdd(address, address); + _endpointListener(address); } LogRequest(_logger, request); diff --git a/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs index f1112ae0b..28fc094f7 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs @@ -38,7 +38,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer public bool Throttle { get; set; } public long ThrottleLimit { get; set; } - + public long MinThrottlePosition; + /// <summary> /// Initializes a new instance of the <see cref="StreamWriter" /> class. /// </summary> @@ -84,7 +85,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer { responseStream = new ThrottledStream(responseStream, ThrottleLimit) { - MinThrottlePosition = ThrottleLimit * 180 + MinThrottlePosition = MinThrottlePosition }; } var task = WriteToAsync(responseStream); |
