mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-05 17:56:18 +00:00
avoid buffering http responses
This commit is contained in:
@@ -19,6 +19,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Common.Security;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
@@ -45,16 +46,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly INetworkManager _networkManager;
|
||||
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
||||
|
||||
public HttpListenerHost(IApplicationHost applicationHost,
|
||||
ILogManager logManager,
|
||||
IServerConfigurationManager config,
|
||||
string serviceName,
|
||||
string defaultRedirectPath, INetworkManager networkManager, params Assembly[] assembliesWithServices)
|
||||
string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamProvider memoryStreamProvider, params Assembly[] assembliesWithServices)
|
||||
: base(serviceName, assembliesWithServices)
|
||||
{
|
||||
DefaultRedirectPath = defaultRedirectPath;
|
||||
_networkManager = networkManager;
|
||||
_memoryStreamProvider = memoryStreamProvider;
|
||||
_config = config;
|
||||
|
||||
_logger = logManager.GetLogger("HttpServer");
|
||||
@@ -95,6 +98,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
|
||||
container.Adapter = _containerAdapter;
|
||||
|
||||
Plugins.RemoveAll(x => x is NativeTypesFeature);
|
||||
Plugins.Add(new SwaggerFeature());
|
||||
Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization"));
|
||||
|
||||
@@ -179,7 +183,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
|
||||
private IHttpListener GetListener()
|
||||
{
|
||||
return new WebSocketSharpListener(_logger, CertificatePath);
|
||||
return new WebSocketSharpListener(_logger, CertificatePath, _memoryStreamProvider);
|
||||
}
|
||||
|
||||
private void OnWebSocketConnecting(WebSocketConnectingEventArgs args)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Net;
|
||||
@@ -15,23 +16,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
/// <summary>
|
||||
/// Creates the server.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">The application host.</param>
|
||||
/// <param name="logManager">The log manager.</param>
|
||||
/// <param name="config">The configuration.</param>
|
||||
/// <param name="_networkmanager">The _networkmanager.</param>
|
||||
/// <param name="serverName">Name of the server.</param>
|
||||
/// <param name="defaultRedirectpath">The default redirectpath.</param>
|
||||
/// <returns>IHttpServer.</returns>
|
||||
public static IHttpServer CreateServer(IApplicationHost applicationHost,
|
||||
ILogManager logManager,
|
||||
IServerConfigurationManager config,
|
||||
INetworkManager _networkmanager,
|
||||
IMemoryStreamProvider streamProvider,
|
||||
string serverName,
|
||||
string defaultRedirectpath)
|
||||
{
|
||||
LogManager.LogFactory = new ServerLogFactory(logManager);
|
||||
|
||||
return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager);
|
||||
return new HttpListenerHost(applicationHost, logManager, config, serverName, defaultRedirectpath, _networkmanager, streamProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
||||
if (boundary == null)
|
||||
return;
|
||||
|
||||
using (var requestStream = GetSubStream(InputStream))
|
||||
using (var requestStream = GetSubStream(InputStream, _memoryStreamProvider))
|
||||
{
|
||||
//DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request
|
||||
//Not ending with \r\n?
|
||||
var ms = new MemoryStream(32 * 1024);
|
||||
var ms = _memoryStreamProvider.CreateNew(32 * 1024);
|
||||
await requestStream.CopyToAsync(ms).ConfigureAwait(false);
|
||||
|
||||
var input = ms;
|
||||
@@ -229,9 +229,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
||||
|
||||
async Task LoadWwwForm()
|
||||
{
|
||||
using (Stream input = GetSubStream(InputStream))
|
||||
using (Stream input = GetSubStream(InputStream, _memoryStreamProvider))
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var ms = _memoryStreamProvider.CreateNew())
|
||||
{
|
||||
await input.CopyToAsync(ms).ConfigureAwait(false);
|
||||
ms.Position = 0;
|
||||
|
||||
@@ -9,6 +9,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.IO;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
||||
{
|
||||
@@ -18,11 +19,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _certificatePath;
|
||||
private readonly IMemoryStreamProvider _memoryStreamProvider;
|
||||
|
||||
public WebSocketSharpListener(ILogger logger, string certificatePath)
|
||||
public WebSocketSharpListener(ILogger logger, string certificatePath, IMemoryStreamProvider memoryStreamProvider)
|
||||
{
|
||||
_logger = logger;
|
||||
_certificatePath = certificatePath;
|
||||
_memoryStreamProvider = memoryStreamProvider;
|
||||
}
|
||||
|
||||
public Action<Exception, IRequest> ErrorHandler { get; set; }
|
||||
@@ -148,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
||||
{
|
||||
var operationName = httpContext.Request.GetOperationName();
|
||||
|
||||
var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger);
|
||||
var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger, _memoryStreamProvider);
|
||||
req.RequestAttributes = req.GetAttributes();
|
||||
|
||||
return req;
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Funq;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using ServiceStack;
|
||||
using ServiceStack.Host;
|
||||
@@ -16,11 +17,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
||||
public Container Container { get; set; }
|
||||
private readonly HttpListenerRequest request;
|
||||
private readonly IHttpResponse response;
|
||||
private IMemoryStreamProvider _memoryStreamProvider;
|
||||
|
||||
public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger)
|
||||
public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger, IMemoryStreamProvider memoryStreamProvider)
|
||||
{
|
||||
this.OperationName = operationName;
|
||||
this.RequestAttributes = requestAttributes;
|
||||
_memoryStreamProvider = memoryStreamProvider;
|
||||
this.request = httpContext.Request;
|
||||
this.response = new WebSocketSharpResponse(logger, httpContext.Response, this);
|
||||
|
||||
@@ -403,7 +406,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
||||
set
|
||||
{
|
||||
bufferedStream = value
|
||||
? bufferedStream ?? new MemoryStream(request.InputStream.ReadFully())
|
||||
? bufferedStream ?? _memoryStreamProvider.CreateNew(request.InputStream.ReadFully())
|
||||
: null;
|
||||
}
|
||||
}
|
||||
@@ -447,7 +450,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
|
||||
}
|
||||
}
|
||||
|
||||
static Stream GetSubStream(Stream stream)
|
||||
static Stream GetSubStream(Stream stream, IMemoryStreamProvider streamProvider)
|
||||
{
|
||||
if (stream is MemoryStream)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.IO;
|
||||
using ServiceStack;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
@@ -17,7 +18,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
private ILogger Logger { get; set; }
|
||||
|
||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source stream.
|
||||
/// </summary>
|
||||
@@ -39,6 +40,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
|
||||
public Action OnComplete { get; set; }
|
||||
public Action OnError { get; set; }
|
||||
private readonly byte[] _bytes;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StreamWriter" /> class.
|
||||
@@ -73,6 +75,17 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
public StreamWriter(byte[] source, string contentType, ILogger logger)
|
||||
: this(new MemoryStream(source), contentType, logger)
|
||||
{
|
||||
if (string.IsNullOrEmpty(contentType))
|
||||
{
|
||||
throw new ArgumentNullException("contentType");
|
||||
}
|
||||
|
||||
_bytes = source;
|
||||
Logger = logger;
|
||||
|
||||
Options["Content-Type"] = contentType;
|
||||
|
||||
Options["Content-Length"] = source.Length.ToString(UsCulture);
|
||||
}
|
||||
|
||||
private const int BufferSize = 81920;
|
||||
@@ -85,9 +98,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var src = SourceStream)
|
||||
if (_bytes != null)
|
||||
{
|
||||
src.CopyTo(responseStream, BufferSize);
|
||||
responseStream.Write(_bytes, 0, _bytes.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var src = SourceStream)
|
||||
{
|
||||
src.CopyTo(responseStream, BufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -114,9 +134,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var src = SourceStream)
|
||||
if (_bytes != null)
|
||||
{
|
||||
await src.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false);
|
||||
await responseStream.WriteAsync(_bytes, 0, _bytes.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var src = SourceStream)
|
||||
{
|
||||
await src.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
Reference in New Issue
Block a user