From 433254c498d2e43acfd34e5c4fcee2fdcc2e767b Mon Sep 17 00:00:00 2001 From: softworkz Date: Fri, 5 Aug 2016 06:08:11 +0200 Subject: Async stream handling: Use interface instead of Func No functional changes --- .../HttpServer/AsyncStreamWriter.cs | 59 ++++++++ .../HttpServer/AsyncStreamWriterEx.cs | 153 +++++++++++++++++++++ .../HttpServer/AsyncStreamWriterFunc.cs | 56 -------- .../HttpServer/HttpResultFactory.cs | 9 +- 4 files changed, 219 insertions(+), 58 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriter.cs create mode 100644 MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterEx.cs delete mode 100644 MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterFunc.cs (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriter.cs new file mode 100644 index 000000000..e44b0c6af --- /dev/null +++ b/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriter.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using ServiceStack; +using ServiceStack.Web; +using MediaBrowser.Controller.Net; + +namespace MediaBrowser.Server.Implementations.HttpServer +{ + public class AsyncStreamWriter : IStreamWriter, IAsyncStreamWriter, IHasOptions + { + /// + /// Gets or sets the source stream. + /// + /// The source stream. + private IAsyncStreamSource _source; + + public Action OnComplete { get; set; } + public Action OnError { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public AsyncStreamWriter(IAsyncStreamSource source) + { + _source = source; + } + + public IDictionary Options + { + get + { + var hasOptions = _source as IHasOptions; + if (hasOptions != null) + { + return hasOptions.Options; + } + + return new Dictionary(StringComparer.OrdinalIgnoreCase); + } + } + + /// + /// Writes to. + /// + /// The response stream. + public void WriteTo(Stream responseStream) + { + var task = _source.WriteToAsync(responseStream); + Task.WaitAll(task); + } + + public async Task WriteToAsync(Stream responseStream) + { + await _source.WriteToAsync(responseStream).ConfigureAwait(false); + } + } +} diff --git a/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterEx.cs b/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterEx.cs new file mode 100644 index 000000000..b98addb31 --- /dev/null +++ b/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterEx.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using ServiceStack; +using ServiceStack.Web; +using MediaBrowser.Controller.Net; + +namespace MediaBrowser.Server.Implementations.HttpServer +{ + public class AsyncStreamWriterEx : AsyncStreamWriter, IHttpResult + { + /// + /// Gets or sets the source stream. + /// + /// The source stream. + private IAsyncStreamSource _source; + + /// + /// Initializes a new instance of the class. + /// + public AsyncStreamWriterEx(IAsyncStreamSource source) : base(source) + { + _source = source; + } + + public string ContentType + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public List Cookies + { + get { throw new NotImplementedException(); } + } + + public Dictionary Headers + { + get { throw new NotImplementedException(); } + } + + public int PaddingLength + { + get + { + return Result.PaddingLength; + } + set + { + Result.PaddingLength = value; + } + } + + public IRequest RequestContext + { + get + { + return Result.RequestContext; + } + set + { + Result.RequestContext = value; + } + } + + public object Response + { + get + { + return Result.Response; + } + set + { + Result.Response = value; + } + } + + public IContentTypeWriter ResponseFilter + { + get + { + return Result.ResponseFilter; + } + set + { + Result.ResponseFilter = value; + } + } + + public Func ResultScope + { + get + { + return Result.ResultScope; + } + set + { + Result.ResultScope = value; + } + } + + public int Status + { + get + { + return Result.Status; + } + set + { + Result.Status = value; + } + } + + public System.Net.HttpStatusCode StatusCode + { + get + { + return Result.StatusCode; + } + set + { + Result.StatusCode = value; + } + } + + public string StatusDescription + { + get + { + return Result.StatusDescription; + } + set + { + Result.StatusDescription = value; + } + } + + private IHttpResult Result + { + get + { + return _source as IHttpResult; + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterFunc.cs b/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterFunc.cs deleted file mode 100644 index 5aa01c706..000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterFunc.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using ServiceStack; -using ServiceStack.Web; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public class AsyncStreamWriterFunc : IStreamWriter, IAsyncStreamWriter, IHasOptions - { - /// - /// Gets or sets the source stream. - /// - /// The source stream. - private Func Writer { get; set; } - - /// - /// Gets the options. - /// - /// The options. - public IDictionary Options { get; private set; } - - public Action OnComplete { get; set; } - public Action OnError { get; set; } - - /// - /// Initializes a new instance of the class. - /// - public AsyncStreamWriterFunc(Func writer, IDictionary headers) - { - Writer = writer; - - if (headers == null) - { - headers = new Dictionary(StringComparer.OrdinalIgnoreCase); - } - Options = headers; - } - - /// - /// Writes to. - /// - /// The response stream. - public void WriteTo(Stream responseStream) - { - var task = Writer(responseStream); - Task.WaitAll(task); - } - - public async Task WriteToAsync(Stream responseStream) - { - await Writer(responseStream).ConfigureAwait(false); - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index c0a2a5eb3..f234674d8 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -704,9 +704,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer throw error; } - public object GetAsyncStreamWriter(Func streamWriter, IDictionary responseHeaders = null) + public object GetAsyncStreamWriter(IAsyncStreamSource streamSource) { - return new AsyncStreamWriterFunc(streamWriter, responseHeaders); + if (streamSource as IHttpResult != null) + { + return new AsyncStreamWriterEx(streamSource); + } + + return new AsyncStreamWriter(streamSource); } } } \ No newline at end of file -- cgit v1.2.3 From 7d16988b1b81cc73608c07d61eabb83f8fcbbb05 Mon Sep 17 00:00:00 2001 From: softworkz Date: Fri, 5 Aug 2016 19:07:43 +0200 Subject: Remove handling IHttpResult --- .../HttpServer/AsyncStreamWriterEx.cs | 153 --------------------- .../HttpServer/HttpResultFactory.cs | 5 - .../MediaBrowser.Server.Implementations.csproj | 1 - 3 files changed, 159 deletions(-) delete mode 100644 MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterEx.cs (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterEx.cs b/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterEx.cs deleted file mode 100644 index b98addb31..000000000 --- a/MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterEx.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using ServiceStack; -using ServiceStack.Web; -using MediaBrowser.Controller.Net; - -namespace MediaBrowser.Server.Implementations.HttpServer -{ - public class AsyncStreamWriterEx : AsyncStreamWriter, IHttpResult - { - /// - /// Gets or sets the source stream. - /// - /// The source stream. - private IAsyncStreamSource _source; - - /// - /// Initializes a new instance of the class. - /// - public AsyncStreamWriterEx(IAsyncStreamSource source) : base(source) - { - _source = source; - } - - public string ContentType - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public List Cookies - { - get { throw new NotImplementedException(); } - } - - public Dictionary Headers - { - get { throw new NotImplementedException(); } - } - - public int PaddingLength - { - get - { - return Result.PaddingLength; - } - set - { - Result.PaddingLength = value; - } - } - - public IRequest RequestContext - { - get - { - return Result.RequestContext; - } - set - { - Result.RequestContext = value; - } - } - - public object Response - { - get - { - return Result.Response; - } - set - { - Result.Response = value; - } - } - - public IContentTypeWriter ResponseFilter - { - get - { - return Result.ResponseFilter; - } - set - { - Result.ResponseFilter = value; - } - } - - public Func ResultScope - { - get - { - return Result.ResultScope; - } - set - { - Result.ResultScope = value; - } - } - - public int Status - { - get - { - return Result.Status; - } - set - { - Result.Status = value; - } - } - - public System.Net.HttpStatusCode StatusCode - { - get - { - return Result.StatusCode; - } - set - { - Result.StatusCode = value; - } - } - - public string StatusDescription - { - get - { - return Result.StatusDescription; - } - set - { - Result.StatusDescription = value; - } - } - - private IHttpResult Result - { - get - { - return _source as IHttpResult; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index f234674d8..b26cf5b76 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -706,11 +706,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer public object GetAsyncStreamWriter(IAsyncStreamSource streamSource) { - if (streamSource as IHttpResult != null) - { - return new AsyncStreamWriterEx(streamSource); - } - return new AsyncStreamWriter(streamSource); } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 8025e3594..07cb9fa0d 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -156,7 +156,6 @@ - -- cgit v1.2.3 From 319dcda4beb5cde9cd858a33a9603f0cff54d831 Mon Sep 17 00:00:00 2001 From: Softworkz Date: Sat, 13 Aug 2016 06:57:21 +0200 Subject: Fix: ETag-Values MUST be quoted according to W3C spec --- MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index c0a2a5eb3..194904320 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -275,7 +275,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// System.Object. private object GetCachedResult(IRequest requestContext, IDictionary responseHeaders, Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType) { - responseHeaders["ETag"] = cacheKeyString; + responseHeaders["ETag"] = string.Format("\"{0}\"", cacheKeyString); if (IsNotModified(requestContext, cacheKey, lastDateModified, cacheDuration)) { -- cgit v1.2.3 From 7dbeeadea6edff204276bf87c03c85886d0ff321 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 13 Aug 2016 20:52:32 -0400 Subject: fix lastmodified header --- MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs index 194904320..27065d0f5 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -534,7 +534,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer if (lastDateModified.HasValue && (string.IsNullOrEmpty(cacheKey) || cacheDuration.HasValue)) { AddAgeHeader(responseHeaders, lastDateModified); - responseHeaders["LastModified"] = lastDateModified.Value.ToString("r"); + responseHeaders["Last-Modified"] = lastDateModified.Value.ToString("r"); } if (cacheDuration.HasValue) -- cgit v1.2.3 From 389487638ec358c975f7573c8b6132525f3925ab Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 18 Aug 2016 02:26:47 -0400 Subject: fixes #1851 - EmbyServer crashes if staticly assigned IP address changes --- .../HttpServer/HttpListenerHost.cs | 50 ++++++++++++++++++++++ .../ApplicationHost.cs | 35 +-------------- 2 files changed, 52 insertions(+), 33 deletions(-) (limited to 'MediaBrowser.Server.Implementations/HttpServer') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 90055d8ec..633208739 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -331,6 +331,46 @@ namespace MediaBrowser.Server.Implementations.HttpServer return url; } + private string NormalizeConfiguredLocalAddress(string address) + { + var index = address.Trim('/').IndexOf('/'); + + if (index != -1) + { + address = address.Substring(index + 1); + } + + return address.Trim('/'); + } + + private bool ValidateHost(Uri url) + { + var hosts = _config + .Configuration + .LocalNetworkAddresses + .Select(NormalizeConfiguredLocalAddress) + .ToList(); + + if (hosts.Count == 0) + { + return true; + } + + var host = url.Host ?? string.Empty; + + _logger.Debug("Validating host {0}", host); + + if (_networkManager.IsInPrivateAddressSpace(host)) + { + hosts.Add("localhost"); + hosts.Add("127.0.0.1"); + + return hosts.Any(i => host.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1); + } + + return true; + } + /// /// Overridable method that can be used to implement a custom hnandler /// @@ -350,6 +390,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer return ; } + if (!ValidateHost(url)) + { + httpRes.StatusCode = 400; + httpRes.ContentType = "text/plain"; + httpRes.Write("Invalid host"); + + httpRes.Close(); + return; + } + var operationName = httpReq.OperationName; var localPath = url.LocalPath; diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 74438abbc..9eb8a4736 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -821,42 +821,11 @@ namespace MediaBrowser.Server.Startup.Common private string CertificatePath { get; set; } - private string NormalizeConfiguredLocalAddress(string address) - { - var index = address.Trim('/').IndexOf('/'); - - if (index != -1) - { - address = address.Substring(index + 1); - } - - return address.Trim('/'); - } private IEnumerable GetUrlPrefixes() { - var hosts = ServerConfigurationManager - .Configuration - .LocalNetworkAddresses - .Select(NormalizeConfiguredLocalAddress) - .ToList(); + var hosts = new List(); - if (hosts.Count == 0) - { - hosts.Add("+"); - } - - if (!hosts.Contains("+", StringComparer.OrdinalIgnoreCase)) - { - if (!hosts.Contains("localhost", StringComparer.OrdinalIgnoreCase)) - { - hosts.Add("localhost"); - } - - if (!hosts.Contains("127.0.0.1", StringComparer.OrdinalIgnoreCase)) - { - hosts.Add("127.0.0.1"); - } - } + hosts.Add("+"); return hosts.SelectMany(i => { -- cgit v1.2.3