aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/HttpServer
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/HttpServer')
-rw-r--r--Emby.Server.Implementations/HttpServer/FileWriter.cs3
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpListenerHost.cs155
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpResultFactory.cs268
-rw-r--r--Emby.Server.Implementations/HttpServer/IHttpListener.cs4
-rw-r--r--Emby.Server.Implementations/HttpServer/LoggerUtils.cs19
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthService.cs36
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs15
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/SessionContext.cs12
-rw-r--r--Emby.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs3
-rw-r--r--Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs1
-rw-r--r--Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs27
-rw-r--r--Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs40
-rw-r--r--Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs1
13 files changed, 218 insertions, 366 deletions
diff --git a/Emby.Server.Implementations/HttpServer/FileWriter.cs b/Emby.Server.Implementations/HttpServer/FileWriter.cs
index 8cb7b5dbf..aa679e1b9 100644
--- a/Emby.Server.Implementations/HttpServer/FileWriter.cs
+++ b/Emby.Server.Implementations/HttpServer/FileWriter.cs
@@ -160,6 +160,9 @@ namespace Emby.Server.Implementations.HttpServer
if (string.IsNullOrWhiteSpace(RangeHeader) || (RangeStart <= 0 && RangeEnd >= TotalContentLength - 1))
{
Logger.Info("Transmit file {0}", Path);
+
+ //var count = FileShare == FileShareMode.ReadWrite ? TotalContentLength : 0;
+
await response.TransmitFile(Path, 0, 0, FileShare, cancellationToken).ConfigureAwait(false);
return;
}
diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
index 05f78eba9..86df798d0 100644
--- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -7,10 +7,10 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using Emby.Server.Implementations.HttpServer;
using Emby.Server.Implementations.HttpServer.SocketSharp;
using Emby.Server.Implementations.Services;
using MediaBrowser.Common.Net;
@@ -24,8 +24,6 @@ using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services;
using MediaBrowser.Model.System;
using MediaBrowser.Model.Text;
-using SocketHttpListener.Net;
-using SocketHttpListener.Primitives;
namespace Emby.Server.Implementations.HttpServer
{
@@ -34,7 +32,7 @@ namespace Emby.Server.Implementations.HttpServer
private string DefaultRedirectPath { get; set; }
private readonly ILogger _logger;
- public IEnumerable<string> UrlPrefixes { get; private set; }
+ public string[] UrlPrefixes { get; private set; }
private readonly List<IService> _restServices = new List<IService>();
@@ -56,14 +54,13 @@ namespace Emby.Server.Implementations.HttpServer
private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer;
private readonly IXmlSerializer _xmlSerializer;
- private readonly ICertificate _certificate;
+ private readonly X509Certificate _certificate;
private readonly IEnvironmentInfo _environment;
- private readonly IStreamFactory _streamFactory;
private readonly Func<Type, Func<string, object>> _funcParseFn;
private readonly bool _enableDualModeSockets;
- public List<Action<IRequest, IResponse, object>> RequestFilters { get; set; }
- public List<Action<IRequest, IResponse, object>> ResponseFilters { get; set; }
+ public Action<IRequest, IResponse, object>[] RequestFilters { get; set; }
+ public Action<IRequest, IResponse, object>[] ResponseFilters { get; set; }
private readonly Dictionary<Type, Type> ServiceOperationsMap = new Dictionary<Type, Type>();
public static HttpListenerHost Instance { get; protected set; }
@@ -72,7 +69,7 @@ namespace Emby.Server.Implementations.HttpServer
ILogger logger,
IServerConfigurationManager config,
string serviceName,
- string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IJsonSerializer jsonSerializer, IXmlSerializer xmlSerializer, IEnvironmentInfo environment, ICertificate certificate, IStreamFactory streamFactory, Func<Type, Func<string, object>> funcParseFn, bool enableDualModeSockets, IFileSystem fileSystem)
+ string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IJsonSerializer jsonSerializer, IXmlSerializer xmlSerializer, IEnvironmentInfo environment, X509Certificate certificate, Func<Type, Func<string, object>> funcParseFn, bool enableDualModeSockets, IFileSystem fileSystem)
{
Instance = this;
@@ -87,7 +84,6 @@ namespace Emby.Server.Implementations.HttpServer
_xmlSerializer = xmlSerializer;
_environment = environment;
_certificate = certificate;
- _streamFactory = streamFactory;
_funcParseFn = funcParseFn;
_enableDualModeSockets = enableDualModeSockets;
_fileSystem = fileSystem;
@@ -95,8 +91,8 @@ namespace Emby.Server.Implementations.HttpServer
_logger = logger;
- RequestFilters = new List<Action<IRequest, IResponse, object>>();
- ResponseFilters = new List<Action<IRequest, IResponse, object>>();
+ RequestFilters = new Action<IRequest, IResponse, object>[] { };
+ ResponseFilters = new Action<IRequest, IResponse, object>[] { };
}
public string GlobalResponse { get; set; }
@@ -125,13 +121,6 @@ namespace Emby.Server.Implementations.HttpServer
return _appHost.CreateInstance(type);
}
- private ServiceController CreateServiceController()
- {
- var types = _restServices.Select(r => r.GetType()).ToArray();
-
- return new ServiceController(() => types);
- }
-
/// <summary>
/// Applies the request filters. Returns whether or not the request has been handled
/// and no more processing should be done.
@@ -142,7 +131,9 @@ namespace Emby.Server.Implementations.HttpServer
//Exec all RequestFilter attributes with Priority < 0
var attributes = GetRequestFilterAttributes(requestDto.GetType());
var i = 0;
- for (; i < attributes.Length && attributes[i].Priority < 0; i++)
+ var count = attributes.Count;
+
+ for (; i < count && attributes[i].Priority < 0; i++)
{
var attribute = attributes[i];
attribute.RequestFilter(req, res, requestDto);
@@ -155,7 +146,7 @@ namespace Emby.Server.Implementations.HttpServer
}
//Exec remaining RequestFilter attributes with Priority >= 0
- for (; i < attributes.Length && attributes[i].Priority >= 0; i++)
+ for (; i < count && attributes[i].Priority >= 0; i++)
{
var attribute = attributes[i];
attribute.RequestFilter(req, res, requestDto);
@@ -169,12 +160,12 @@ namespace Emby.Server.Implementations.HttpServer
return serviceType;
}
- public void AddServiceInfo(Type serviceType, Type requestType, Type responseType)
+ public void AddServiceInfo(Type serviceType, Type requestType)
{
ServiceOperationsMap[requestType] = serviceType;
}
- private IHasRequestFilter[] GetRequestFilterAttributes(Type requestDtoType)
+ private List<IHasRequestFilter> GetRequestFilterAttributes(Type requestDtoType)
{
var attributes = requestDtoType.GetTypeInfo().GetCustomAttributes(true).OfType<IHasRequestFilter>().ToList();
@@ -186,40 +177,13 @@ namespace Emby.Server.Implementations.HttpServer
attributes.Sort((x, y) => x.Priority - y.Priority);
- return attributes.ToArray();
- }
-
- /// <summary>
- /// Starts the Web Service
- /// </summary>
- private void StartListener()
- {
- WebSocketSharpRequest.HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes.First());
-
- _listener = GetListener();
-
- _listener.WebSocketConnected = OnWebSocketConnected;
- _listener.WebSocketConnecting = OnWebSocketConnecting;
- _listener.ErrorHandler = ErrorHandler;
- _listener.RequestHandler = RequestHandler;
-
- _listener.Start(UrlPrefixes);
- }
-
- public static string GetHandlerPathIfAny(string listenerUrl)
- {
- if (listenerUrl == null) return null;
- var pos = listenerUrl.IndexOf("://", StringComparison.OrdinalIgnoreCase);
- if (pos == -1) return null;
- var startHostUrl = listenerUrl.Substring(pos + "://".Length);
- var endPos = startHostUrl.IndexOf('/');
- if (endPos == -1) return null;
- var endHostUrl = startHostUrl.Substring(endPos + 1);
- return string.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/');
+ return attributes;
}
private IHttpListener GetListener()
{
+ //return new KestrelHost.KestrelListener(_logger, _environment, _fileSystem);
+
return new WebSocketSharpListener(_logger,
_certificate,
_memoryStreamProvider,
@@ -227,22 +191,11 @@ namespace Emby.Server.Implementations.HttpServer
_networkManager,
_socketFactory,
_cryptoProvider,
- _streamFactory,
_enableDualModeSockets,
- GetRequest,
_fileSystem,
_environment);
}
- private IHttpRequest GetRequest(HttpListenerContext httpContext)
- {
- var operationName = httpContext.Request.GetOperationName();
-
- var req = new WebSocketSharpRequest(httpContext, operationName, _logger, _memoryStreamProvider);
-
- return req;
- }
-
private void OnWebSocketConnecting(WebSocketConnectingEventArgs args)
{
if (_disposed)
@@ -355,7 +308,8 @@ namespace Emby.Server.Implementations.HttpServer
if (_listener != null)
{
_logger.Info("Stopping HttpListener...");
- _listener.Stop();
+ var task = _listener.Stop();
+ Task.WaitAll(task);
_logger.Info("HttpListener stopped");
}
}
@@ -441,7 +395,7 @@ namespace Emby.Server.Implementations.HttpServer
return address.Trim('/');
}
- private bool ValidateHost(Uri url)
+ private bool ValidateHost(string host)
{
var hosts = _config
.Configuration
@@ -454,7 +408,7 @@ namespace Emby.Server.Implementations.HttpServer
return true;
}
- var host = url.Host ?? string.Empty;
+ host = host ?? string.Empty;
_logger.Debug("Validating host {0}", host);
@@ -472,7 +426,7 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary>
/// Overridable method that can be used to implement a custom hnandler
/// </summary>
- protected async Task RequestHandler(IHttpRequest httpReq, Uri url, CancellationToken cancellationToken)
+ protected async Task RequestHandler(IHttpRequest httpReq, string urlString, string host, string localPath, CancellationToken cancellationToken)
{
var date = DateTime.Now;
var httpRes = httpReq.Response;
@@ -491,7 +445,7 @@ namespace Emby.Server.Implementations.HttpServer
return;
}
- if (!ValidateHost(url))
+ if (!ValidateHost(host))
{
httpRes.StatusCode = 400;
httpRes.ContentType = "text/plain";
@@ -511,9 +465,7 @@ namespace Emby.Server.Implementations.HttpServer
}
var operationName = httpReq.OperationName;
- var localPath = url.LocalPath;
- var urlString = url.OriginalString;
enableLog = EnableLogging(urlString, localPath);
urlToLog = urlString;
logHeaders = enableLog && urlToLog.IndexOf("/videos/", StringComparison.OrdinalIgnoreCase) != -1;
@@ -697,19 +649,26 @@ namespace Emby.Server.Implementations.HttpServer
{
_restServices.AddRange(services);
- ServiceController = CreateServiceController();
+ ServiceController = new ServiceController();
_logger.Info("Calling ServiceStack AppHost.Init");
- ServiceController.Init(this);
+ var types = _restServices.Select(r => r.GetType()).ToArray();
+
+ ServiceController.Init(this, types);
- var requestFilters = _appHost.GetExports<IRequestFilter>().ToList();
- foreach (var filter in requestFilters)
+ var list = new List<Action<IRequest, IResponse, object>>();
+ foreach (var filter in _appHost.GetExports<IRequestFilter>())
{
- RequestFilters.Add(filter.Filter);
+ list.Add(filter.Filter);
}
- ResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
+ RequestFilters = list.ToArray();
+
+ ResponseFilters = new Action<IRequest, IResponse, object>[]
+ {
+ new ResponseFilter(_logger).FilterResponse
+ };
}
public RouteAttribute[] GetRouteAttributes(Type requestType)
@@ -726,22 +685,22 @@ namespace Emby.Server.Implementations.HttpServer
Summary = route.Summary
});
- routes.Add(new RouteAttribute(NormalizeRoutePath(route.Path), route.Verbs)
+ routes.Add(new RouteAttribute(NormalizeMediaBrowserRoutePath(route.Path), route.Verbs)
{
Notes = route.Notes,
Priority = route.Priority,
Summary = route.Summary
});
- routes.Add(new RouteAttribute(DoubleNormalizeEmbyRoutePath(route.Path), route.Verbs)
- {
- Notes = route.Notes,
- Priority = route.Priority,
- Summary = route.Summary
- });
+ //routes.Add(new RouteAttribute(DoubleNormalizeEmbyRoutePath(route.Path), route.Verbs)
+ //{
+ // Notes = route.Notes,
+ // Priority = route.Priority,
+ // Summary = route.Summary
+ //});
}
- return routes.ToArray();
+ return routes.ToArray(routes.Count);
}
public Func<string, object> GetParseFn(Type propertyType)
@@ -779,24 +738,24 @@ namespace Emby.Server.Implementations.HttpServer
return "emby/" + path;
}
- private string DoubleNormalizeEmbyRoutePath(string path)
+ private string NormalizeMediaBrowserRoutePath(string path)
{
if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase))
{
- return "/emby/emby" + path;
+ return "/mediabrowser" + path;
}
- return "emby/emby/" + path;
+ return "mediabrowser/" + path;
}
- private string NormalizeRoutePath(string path)
+ private string DoubleNormalizeEmbyRoutePath(string path)
{
if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase))
{
- return "/mediabrowser" + path;
+ return "/emby/emby" + path;
}
- return "mediabrowser/" + path;
+ return "emby/emby/" + path;
}
private bool _disposed;
@@ -824,10 +783,18 @@ namespace Emby.Server.Implementations.HttpServer
GC.SuppressFinalize(this);
}
- public void StartServer(IEnumerable<string> urlPrefixes)
+ public void StartServer(string[] urlPrefixes)
{
- UrlPrefixes = urlPrefixes.ToList();
- StartListener();
+ UrlPrefixes = urlPrefixes;
+
+ _listener = GetListener();
+
+ _listener.WebSocketConnected = OnWebSocketConnected;
+ _listener.WebSocketConnecting = OnWebSocketConnecting;
+ _listener.ErrorHandler = ErrorHandler;
+ _listener.RequestHandler = RequestHandler;
+
+ _listener.Start(UrlPrefixes);
}
}
} \ No newline at end of file
diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
index 396bd8e88..f5a1fe246 100644
--- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -6,19 +6,16 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
-using System.IO.Compression;
using System.Net;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
-using Emby.Server.Implementations.HttpServer;
using Emby.Server.Implementations.Services;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services;
using IRequest = MediaBrowser.Model.Services.IRequest;
using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
-using StreamWriter = Emby.Server.Implementations.HttpServer.StreamWriter;
namespace Emby.Server.Implementations.HttpServer
{
@@ -193,50 +190,37 @@ namespace Emby.Server.Implementations.HttpServer
/// <returns></returns>
public object ToOptimizedResult<T>(IRequest request, T dto)
{
- var compressionType = GetCompressionType(request);
- if (compressionType == null)
- {
- var contentType = request.ResponseContentType;
+ var contentType = request.ResponseContentType;
- switch (GetRealContentType(contentType))
- {
- case "application/xml":
- case "text/xml":
- case "text/xml; charset=utf-8": //"text/xml; charset=utf-8" also matches xml
- return SerializeToXmlString(dto);
-
- case "application/json":
- case "text/json":
- return _jsonSerializer.SerializeToString(dto);
- }
- }
-
- // Do not use the memoryStreamFactory here, they don't place nice with compression
- using (var ms = new MemoryStream())
+ switch (GetRealContentType(contentType))
{
- var contentType = request.ResponseContentType;
- var writerFn = RequestHelper.GetResponseWriter(HttpListenerHost.Instance, contentType);
+ case "application/xml":
+ case "text/xml":
+ case "text/xml; charset=utf-8": //"text/xml; charset=utf-8" also matches xml
+ return SerializeToXmlString(dto);
- writerFn(dto, ms);
+ case "application/json":
+ case "text/json":
+ return _jsonSerializer.SerializeToString(dto);
+ default:
+ {
+ var ms = new MemoryStream();
+ var writerFn = RequestHelper.GetResponseWriter(HttpListenerHost.Instance, contentType);
- ms.Position = 0;
+ writerFn(dto, ms);
+
+ ms.Position = 0;
- var responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ if (string.Equals(request.Verb, "head", StringComparison.OrdinalIgnoreCase))
+ {
+ return GetHttpResult(new byte[] { }, contentType, true);
+ }
- return GetCompressedResult(ms, compressionType, responseHeaders, false, request.ResponseContentType).Result;
+ return GetHttpResult(ms, contentType, true);
+ }
}
}
- private static Stream GetCompressionStream(Stream outputStream, string compressionType)
- {
- if (compressionType == "deflate")
- return new DeflateStream(outputStream, CompressionMode.Compress, true);
- if (compressionType == "gzip")
- return new GZipStream(outputStream, CompressionMode.Compress, true);
-
- throw new NotSupportedException(compressionType);
- }
-
public static string GetRealContentType(string contentType)
{
return contentType == null
@@ -440,11 +424,14 @@ namespace Emby.Server.Implementations.HttpServer
options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
- // Quotes are valid in linux. They'll possibly cause issues here
- var filename = (Path.GetFileName(path) ?? string.Empty).Replace("\"", string.Empty);
- if (!string.IsNullOrWhiteSpace(filename))
+ if (!options.ResponseHeaders.ContainsKey("Content-Disposition"))
{
- options.ResponseHeaders["Content-Disposition"] = "inline; filename=\"" + filename + "\"";
+ // Quotes are valid in linux. They'll possibly cause issues here
+ var filename = (Path.GetFileName(path) ?? string.Empty).Replace("\"", string.Empty);
+ if (!string.IsNullOrWhiteSpace(filename))
+ {
+ options.ResponseHeaders["Content-Disposition"] = "inline; filename=\"" + filename + "\"";
+ }
}
return GetStaticResult(requestContext, options);
@@ -503,190 +490,67 @@ namespace Emby.Server.Implementations.HttpServer
return result;
}
- var compress = ShouldCompressResponse(requestContext, contentType);
- var hasHeaders = await GetStaticResult(requestContext, options, compress).ConfigureAwait(false);
- AddResponseHeaders(hasHeaders, options.ResponseHeaders);
-
- return hasHeaders;
- }
-
- /// <summary>
- /// Shoulds the compress response.
- /// </summary>
- /// <param name="requestContext">The request context.</param>
- /// <param name="contentType">Type of the content.</param>
- /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- private bool ShouldCompressResponse(IRequest requestContext, string contentType)
- {
- // It will take some work to support compression with byte range requests
- if (!string.IsNullOrWhiteSpace(requestContext.Headers.Get("Range")))
- {
- 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))
- {
- if (string.Equals(contentType, "application/x-javascript", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- if (string.Equals(contentType, "application/xml", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- return false;
- }
-
- return true;
- }
-
- /// <summary>
- /// The us culture
- /// </summary>
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
- private async Task<IHasHeaders> 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 = GetCompressionType(requestContext);
-
- if (!compress || string.IsNullOrEmpty(requestedCompressionType))
- {
- var rangeHeader = requestContext.Headers.Get("Range");
-
- if (!isHeadRequest && !string.IsNullOrWhiteSpace(options.Path))
- {
- return new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem)
- {
- OnComplete = options.OnComplete,
- OnError = options.OnError,
- FileShare = options.FileShare
- };
- }
+ //var requestedCompressionType = GetCompressionType(requestContext);
- if (!string.IsNullOrWhiteSpace(rangeHeader))
- {
- var stream = await factoryFn().ConfigureAwait(false);
+ var rangeHeader = requestContext.Headers.Get("Range");
- return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest, _logger)
- {
- OnComplete = options.OnComplete
- };
- }
- else
+ if (!isHeadRequest && !string.IsNullOrWhiteSpace(options.Path))
+ {
+ var hasHeaders = new FileWriter(options.Path, contentType, rangeHeader, _logger, _fileSystem)
{
- var stream = await factoryFn().ConfigureAwait(false);
-
- responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture);
-
- if (isHeadRequest)
- {
- stream.Dispose();
-
- return GetHttpResult(new byte[] { }, contentType, true);
- }
+ OnComplete = options.OnComplete,
+ OnError = options.OnError,
+ FileShare = options.FileShare
+ };
- return new StreamWriter(stream, contentType, _logger)
- {
- OnComplete = options.OnComplete,
- OnError = options.OnError
- };
- }
+ AddResponseHeaders(hasHeaders, options.ResponseHeaders);
+ return hasHeaders;
}
- using (var stream = await factoryFn().ConfigureAwait(false))
+ if (!string.IsNullOrWhiteSpace(rangeHeader))
{
- return await GetCompressedResult(stream, requestedCompressionType, responseHeaders, isHeadRequest, contentType).ConfigureAwait(false);
- }
- }
+ var stream = await factoryFn().ConfigureAwait(false);
- private async Task<IHasHeaders> GetCompressedResult(Stream stream,
- string requestedCompressionType,
- IDictionary<string, string> responseHeaders,
- bool isHeadRequest,
- string contentType)
- {
- using (var reader = new MemoryStream())
- {
- await stream.CopyToAsync(reader).ConfigureAwait(false);
-
- reader.Position = 0;
- var content = reader.ToArray();
-
- if (content.Length >= 1024)
+ var hasHeaders = new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest, _logger)
{
- content = Compress(content, requestedCompressionType);
- responseHeaders["Content-Encoding"] = requestedCompressionType;
- }
+ OnComplete = options.OnComplete
+ };
- responseHeaders["Vary"] = "Accept-Encoding";
- responseHeaders["Content-Length"] = content.Length.ToString(UsCulture);
+ AddResponseHeaders(hasHeaders, options.ResponseHeaders);
+ return hasHeaders;
+ }
+ else
+ {
+ var stream = await factoryFn().ConfigureAwait(false);
+
+ responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture);
if (isHeadRequest)
{
+ stream.Dispose();
+
return GetHttpResult(new byte[] { }, contentType, true);
}
- return GetHttpResult(content, contentType, true, responseHeaders);
- }
- }
-
- private byte[] Compress(byte[] bytes, string compressionType)
- {
- if (compressionType == "deflate")
- return Deflate(bytes);
-
- if (compressionType == "gzip")
- return GZip(bytes);
-
- throw new NotSupportedException(compressionType);
- }
-
- private byte[] Deflate(byte[] bytes)
- {
- // In .NET FX incompat-ville, you can't access compressed bytes without closing DeflateStream
- // Which means we must use MemoryStream since you have to use ToArray() on a closed Stream
- using (var ms = new MemoryStream())
- using (var zipStream = new DeflateStream(ms, CompressionMode.Compress))
- {
- zipStream.Write(bytes, 0, bytes.Length);
- zipStream.Dispose();
+ var hasHeaders = new StreamWriter(stream, contentType, _logger)
+ {
+ OnComplete = options.OnComplete,
+ OnError = options.OnError
+ };
- return ms.ToArray();
+ AddResponseHeaders(hasHeaders, options.ResponseHeaders);
+ return hasHeaders;
}
}
- private byte[] GZip(byte[] buffer)
- {
- using (var ms = new MemoryStream())
- using (var zipStream = new GZipStream(ms, CompressionMode.Compress))
- {
- zipStream.Write(buffer, 0, buffer.Length);
- zipStream.Dispose();
-
- return ms.ToArray();
- }
- }
+ /// <summary>
+ /// The us culture
+ /// </summary>
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary>
/// Adds the caching responseHeaders.
diff --git a/Emby.Server.Implementations/HttpServer/IHttpListener.cs b/Emby.Server.Implementations/HttpServer/IHttpListener.cs
index 82175dbed..9feb2311d 100644
--- a/Emby.Server.Implementations/HttpServer/IHttpListener.cs
+++ b/Emby.Server.Implementations/HttpServer/IHttpListener.cs
@@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.HttpServer
/// Gets or sets the request handler.
/// </summary>
/// <value>The request handler.</value>
- Func<IHttpRequest, Uri, CancellationToken, Task> RequestHandler { get; set; }
+ Func<IHttpRequest, string, string, string, CancellationToken, Task> RequestHandler { get; set; }
/// <summary>
/// Gets or sets the web socket handler.
@@ -42,6 +42,6 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary>
/// Stops this instance.
/// </summary>
- void Stop();
+ Task Stop();
}
}
diff --git a/Emby.Server.Implementations/HttpServer/LoggerUtils.cs b/Emby.Server.Implementations/HttpServer/LoggerUtils.cs
index f0e75eea4..46bb4c7f9 100644
--- a/Emby.Server.Implementations/HttpServer/LoggerUtils.cs
+++ b/Emby.Server.Implementations/HttpServer/LoggerUtils.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Model.Logging;
using System;
using System.Globalization;
-using System.Linq;
using MediaBrowser.Model.Services;
using SocketHttpListener.Net;
@@ -29,7 +28,20 @@ namespace Emby.Server.Implementations.HttpServer
}
else
{
- var headerText = string.Join(", ", headers.Select(i => i.Name + "=" + i.Value).ToArray());
+ var headerText = string.Empty;
+ var index = 0;
+
+ foreach (var i in headers)
+ {
+ if (index > 0)
+ {
+ headerText += ", ";
+ }
+
+ headerText += i.Name + "=" + i.Value;
+
+ index++;
+ }
logger.Info("HTTP {0} {1}. {2}", method, url, headerText);
}
@@ -48,7 +60,8 @@ namespace Emby.Server.Implementations.HttpServer
var durationMs = duration.TotalMilliseconds;
var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms";
- var headerText = headers == null ? string.Empty : "Headers: " + string.Join(", ", headers.Where(i => i.Name.IndexOf("Access-", StringComparison.OrdinalIgnoreCase) == -1).Select(i => i.Name + "=" + i.Value).ToArray());
+ //var headerText = headers == null ? string.Empty : "Headers: " + string.Join(", ", headers.Where(i => i.Name.IndexOf("Access-", StringComparison.OrdinalIgnoreCase) == -1).Select(i => i.Name + "=" + i.Value).ToArray());
+ var headerText = string.Empty;
logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4} {5}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url, headerText);
}
}
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
index 4d00c9b19..fadab4482 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -7,8 +7,8 @@ using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using System;
-using System.Collections.Generic;
using System.Linq;
+using MediaBrowser.Model.Services;
namespace Emby.Server.Implementations.HttpServer.Security
{
@@ -38,19 +38,19 @@ namespace Emby.Server.Implementations.HttpServer.Security
/// </summary>
public string HtmlRedirect { get; set; }
- public void Authenticate(IServiceRequest request,
+ public void Authenticate(IRequest request,
IAuthenticationAttributes authAttribtues)
{
ValidateUser(request, authAttribtues);
}
- private void ValidateUser(IServiceRequest request,
+ private void ValidateUser(IRequest request,
IAuthenticationAttributes authAttribtues)
{
// This code is executed before the service
var auth = AuthorizationContext.GetAuthorizationInfo(request);
- if (!IsExemptFromAuthenticationToken(auth, authAttribtues))
+ if (!IsExemptFromAuthenticationToken(auth, authAttribtues, request))
{
var valid = IsValidConnectKey(auth.Token);
@@ -76,9 +76,9 @@ namespace Emby.Server.Implementations.HttpServer.Security
var info = GetTokenInfo(request);
- if (!IsExemptFromRoles(auth, authAttribtues, info))
+ if (!IsExemptFromRoles(auth, authAttribtues, request, info))
{
- var roles = authAttribtues.GetRoles().ToList();
+ var roles = authAttribtues.GetRoles();
ValidateRoles(roles, user);
}
@@ -96,7 +96,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
}
}
- private void ValidateUserAccess(User user, IServiceRequest request,
+ private void ValidateUserAccess(User user, IRequest request,
IAuthenticationAttributes authAttribtues,
AuthorizationInfo auth)
{
@@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
!authAttribtues.EscapeParentalControl &&
!user.IsParentalScheduleAllowed())
{
- request.AddResponseHeader("X-Application-Error-Code", "ParentalControl");
+ request.Response.AddHeader("X-Application-Error-Code", "ParentalControl");
throw new SecurityException("This user account is not allowed access at this time.")
{
@@ -132,23 +132,33 @@ namespace Emby.Server.Implementations.HttpServer.Security
}
}
- private bool IsExemptFromAuthenticationToken(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues)
+ private bool IsExemptFromAuthenticationToken(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, IRequest request)
{
if (!_config.Configuration.IsStartupWizardCompleted && authAttribtues.AllowBeforeStartupWizard)
{
return true;
}
+ if (authAttribtues.AllowLocal && request.IsLocal)
+ {
+ return true;
+ }
+
return false;
}
- private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, AuthenticationInfo tokenInfo)
+ private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, IRequest request, AuthenticationInfo tokenInfo)
{
if (!_config.Configuration.IsStartupWizardCompleted && authAttribtues.AllowBeforeStartupWizard)
{
return true;
}
+ if (authAttribtues.AllowLocal && request.IsLocal)
+ {
+ return true;
+ }
+
if (string.IsNullOrWhiteSpace(auth.Token))
{
return true;
@@ -162,7 +172,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
return false;
}
- private void ValidateRoles(List<string> roles, User user)
+ private void ValidateRoles(string[] roles, User user)
{
if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
{
@@ -196,7 +206,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
}
}
- private AuthenticationInfo GetTokenInfo(IServiceRequest request)
+ private AuthenticationInfo GetTokenInfo(IRequest request)
{
object info;
request.Items.TryGetValue("OriginalAuthenticationInfo", out info);
@@ -213,7 +223,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
return ConnectManager.IsAuthorizationTokenValid(token);
}
- private void ValidateSecurityToken(IServiceRequest request, string token)
+ private void ValidateSecurityToken(IRequest request, string token)
{
if (string.IsNullOrWhiteSpace(token))
{
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index ede85fb67..c9d5ed007 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -3,8 +3,8 @@ using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security;
using System;
using System.Collections.Generic;
-using System.Linq;
using MediaBrowser.Model.Services;
+using System.Linq;
namespace Emby.Server.Implementations.HttpServer.Security
{
@@ -21,11 +21,10 @@ namespace Emby.Server.Implementations.HttpServer.Security
public AuthorizationInfo GetAuthorizationInfo(object requestContext)
{
- var req = new ServiceRequest((IRequest)requestContext);
- return GetAuthorizationInfo(req);
+ return GetAuthorizationInfo((IRequest)requestContext);
}
- public AuthorizationInfo GetAuthorizationInfo(IServiceRequest requestContext)
+ public AuthorizationInfo GetAuthorizationInfo(IRequest requestContext)
{
object cached;
if (requestContext.Items.TryGetValue("AuthorizationInfo", out cached))
@@ -41,7 +40,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
/// </summary>
/// <param name="httpReq">The HTTP req.</param>
/// <returns>Dictionary{System.StringSystem.String}.</returns>
- private AuthorizationInfo GetAuthorization(IServiceRequest httpReq)
+ private AuthorizationInfo GetAuthorization(IRequest httpReq)
{
var auth = GetAuthorizationDictionary(httpReq);
@@ -90,7 +89,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
AccessToken = token
});
- var tokenInfo = result.Items.FirstOrDefault();
+ var tokenInfo = result.Items.Length > 0 ? result.Items[0] : null;
if (tokenInfo != null)
{
@@ -135,7 +134,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
/// </summary>
/// <param name="httpReq">The HTTP req.</param>
/// <returns>Dictionary{System.StringSystem.String}.</returns>
- private Dictionary<string, string> GetAuthorizationDictionary(IServiceRequest httpReq)
+ private Dictionary<string, string> GetAuthorizationDictionary(IRequest httpReq)
{
var auth = httpReq.Headers["X-Emby-Authorization"];
@@ -161,7 +160,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
// There should be at least to parts
if (parts.Length != 2) return null;
- var acceptedNames = new[] { "MediaBrowser", "Emby"};
+ var acceptedNames = new[] { "MediaBrowser", "Emby" };
// It has to be a digest request
if (!acceptedNames.Contains(parts[0] ?? string.Empty, StringComparer.OrdinalIgnoreCase))
diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
index 33dd4e2d7..dd5d64bf6 100644
--- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
@@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
_sessionManager = sessionManager;
}
- public Task<SessionInfo> GetSession(IServiceRequest requestContext)
+ public Task<SessionInfo> GetSession(IRequest requestContext)
{
var authorization = _authContext.GetAuthorizationInfo(requestContext);
@@ -38,7 +38,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.RemoteIp, user);
}
- private AuthenticationInfo GetTokenInfo(IServiceRequest request)
+ private AuthenticationInfo GetTokenInfo(IRequest request)
{
object info;
request.Items.TryGetValue("OriginalAuthenticationInfo", out info);
@@ -47,11 +47,10 @@ namespace Emby.Server.Implementations.HttpServer.Security
public Task<SessionInfo> GetSession(object requestContext)
{
- var req = new ServiceRequest((IRequest)requestContext);
- return GetSession(req);
+ return GetSession((IRequest)requestContext);
}
- public async Task<User> GetUser(IServiceRequest requestContext)
+ public async Task<User> GetUser(IRequest requestContext)
{
var session = await GetSession(requestContext).ConfigureAwait(false);
@@ -60,8 +59,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
public Task<User> GetUser(object requestContext)
{
- var req = new ServiceRequest((IRequest)requestContext);
- return GetUser(req);
+ return GetUser((IRequest)requestContext);
}
}
}
diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs
index 4fbe0ed94..4e8dd7362 100644
--- a/Emby.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs
+++ b/Emby.Server.Implementations/HttpServer/SocketSharp/HttpUtility.cs
@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Text;
using MediaBrowser.Model.Services;
+using MediaBrowser.Model.Extensions;
namespace Emby.Server.Implementations.HttpServer.SocketSharp
{
@@ -585,7 +586,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
WriteCharBytes(bytes, ch, e);
}
- byte[] buf = bytes.ToArray();
+ byte[] buf = bytes.ToArray(bytes.Count);
bytes = null;
return e.GetString(buf, 0, buf.Length);
diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
index 9823a2ff5..cc7a4557e 100644
--- a/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
+++ b/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
@@ -123,6 +123,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
public void Dispose()
{
Dispose(true);
+ GC.SuppressFinalize(this);
}
/// <summary>
diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
index e648838b2..10aaa4032 100644
--- a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
+++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
@@ -4,6 +4,7 @@ using SocketHttpListener.Net;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
@@ -22,22 +23,20 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
private HttpListener _listener;
private readonly ILogger _logger;
- private readonly ICertificate _certificate;
+ private readonly X509Certificate _certificate;
private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly ITextEncoding _textEncoding;
private readonly INetworkManager _networkManager;
private readonly ISocketFactory _socketFactory;
private readonly ICryptoProvider _cryptoProvider;
- private readonly IStreamFactory _streamFactory;
private readonly IFileSystem _fileSystem;
- private readonly Func<HttpListenerContext, IHttpRequest> _httpRequestFactory;
private readonly bool _enableDualMode;
private readonly IEnvironmentInfo _environment;
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
private CancellationToken _disposeCancellationToken;
- public WebSocketSharpListener(ILogger logger, ICertificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, bool enableDualMode, Func<HttpListenerContext, IHttpRequest> httpRequestFactory, IFileSystem fileSystem, IEnvironmentInfo environment)
+ public WebSocketSharpListener(ILogger logger, X509Certificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, bool enableDualMode, IFileSystem fileSystem, IEnvironmentInfo environment)
{
_logger = logger;
_certificate = certificate;
@@ -46,9 +45,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
_networkManager = networkManager;
_socketFactory = socketFactory;
_cryptoProvider = cryptoProvider;
- _streamFactory = streamFactory;
_enableDualMode = enableDualMode;
- _httpRequestFactory = httpRequestFactory;
_fileSystem = fileSystem;
_environment = environment;
@@ -56,7 +53,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
}
public Action<Exception, IRequest, bool> ErrorHandler { get; set; }
- public Func<IHttpRequest, Uri, CancellationToken, Task> RequestHandler { get; set; }
+ public Func<IHttpRequest, string, string, string, CancellationToken, Task> RequestHandler { get; set; }
public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; }
@@ -65,7 +62,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
public void Start(IEnumerable<string> urlPrefixes)
{
if (_listener == null)
- _listener = new HttpListener(_logger, _cryptoProvider, _streamFactory, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider, _fileSystem, _environment);
+ _listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider, _fileSystem, _environment);
_listener.EnableDualMode = _enableDualMode;
@@ -117,7 +114,9 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
return Task.FromResult(true);
}
- return RequestHandler(httpReq, request.Url, cancellationToken);
+ var uri = request.Url;
+
+ return RequestHandler(httpReq, uri.OriginalString, uri.Host, uri.LocalPath, cancellationToken);
}
private void ProcessWebSocketRequest(HttpListenerContext ctx)
@@ -173,10 +172,14 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
private IHttpRequest GetRequest(HttpListenerContext httpContext)
{
- return _httpRequestFactory(httpContext);
+ var operationName = httpContext.Request.GetOperationName();
+
+ var req = new WebSocketSharpRequest(httpContext, operationName, _logger, _memoryStreamProvider);
+
+ return req;
}
- public void Stop()
+ public Task Stop()
{
_disposeCancellationTokenSource.Cancel();
@@ -189,6 +192,8 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
_listener.Close();
}
+
+ return Task.FromResult(true);
}
public void Dispose()
diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
index 2dfe6a9e3..522377f0c 100644
--- a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
+++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
@@ -27,6 +27,20 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
_memoryStreamProvider = memoryStreamProvider;
this.request = httpContext.Request;
this.response = new WebSocketSharpResponse(logger, httpContext.Response, this);
+
+ //HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]);
+ }
+
+ private static string GetHandlerPathIfAny(string listenerUrl)
+ {
+ if (listenerUrl == null) return null;
+ var pos = listenerUrl.IndexOf("://", StringComparison.OrdinalIgnoreCase);
+ if (pos == -1) return null;
+ var startHostUrl = listenerUrl.Substring(pos + "://".Length);
+ var endPos = startHostUrl.IndexOf('/');
+ if (endPos == -1) return null;
+ var endHostUrl = startHostUrl.Substring(endPos + 1);
+ return string.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/');
}
public HttpListenerRequest HttpRequest
@@ -108,7 +122,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
return remoteIp ??
(remoteIp = (CheckBadChars(XForwardedFor)) ??
(NormalizeIp(CheckBadChars(XRealIp)) ??
- (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.IpAddress.ToString()) : null)));
+ (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null)));
}
}
@@ -232,13 +246,12 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
set
{
this.responseContentType = value;
- HasExplicitResponseContentType = true;
}
}
public const string FormUrlEncoded = "application/x-www-form-urlencoded";
public const string MultiPartFormData = "multipart/form-data";
- private static string GetResponseContentType(IRequest httpReq)
+ public static string GetResponseContentType(IRequest httpReq)
{
var specifiedContentType = GetQueryStringContentType(httpReq);
if (!string.IsNullOrEmpty(specifiedContentType)) return specifiedContentType;
@@ -346,8 +359,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
: strVal.Substring(0, pos);
}
- public bool HasExplicitResponseContentType { get; private set; }
-
public static string HandlerFactoryPath;
private string pathInfo;
@@ -490,13 +501,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
get { return HttpMethod; }
}
- public string Param(string name)
- {
- return Headers[name]
- ?? QueryString[name]
- ?? FormData[name];
- }
-
public string ContentType
{
get { return request.ContentType; }
@@ -584,18 +588,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
return stream;
}
- public static string GetHandlerPathIfAny(string listenerUrl)
- {
- if (listenerUrl == null) return null;
- var pos = listenerUrl.IndexOf("://", StringComparison.OrdinalIgnoreCase);
- if (pos == -1) return null;
- var startHostUrl = listenerUrl.Substring(pos + "://".Length);
- var endPos = startHostUrl.IndexOf('/');
- if (endPos == -1) return null;
- var endHostUrl = startHostUrl.Substring(endPos + 1);
- return String.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/');
- }
-
public static string NormalizePathInfo(string pathInfo, string handlerPath)
{
if (handlerPath != null && pathInfo.TrimStart('/').StartsWith(
diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
index d6762d94b..5b51c0cf1 100644
--- a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
+++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
@@ -29,7 +29,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
}
public IRequest Request { get; private set; }
- public bool UseBufferedStream { get; set; }
public Dictionary<string, object> Items { get; private set; }
public object OriginalResponse
{