aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/HttpServer
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations/HttpServer')
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs14
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs139
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs2
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs23
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs3
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs42
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs13
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs5
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);