rework result factory

This commit is contained in:
Luke Pulverenti
2016-11-10 09:41:24 -05:00
parent c1ae3ec2ce
commit 227dd0a42d
83 changed files with 715 additions and 811 deletions

View File

@@ -6,13 +6,17 @@ 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 MediaBrowser.Model.IO;
using MediaBrowser.Model.Services;
using ServiceStack;
using ServiceStack.Host;
using IRequest = MediaBrowser.Model.Services.IRequest;
using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
using StreamWriter = Emby.Server.Implementations.HttpServer.StreamWriter;
@@ -30,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer;
private readonly IXmlSerializer _xmlSerializer;
/// <summary>
/// Initializes a new instance of the <see cref="HttpResultFactory" /> class.
@@ -37,10 +42,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="logManager">The log manager.</param>
/// <param name="fileSystem">The file system.</param>
/// <param name="jsonSerializer">The json serializer.</param>
public HttpResultFactory(ILogManager logManager, IFileSystem fileSystem, IJsonSerializer jsonSerializer)
public HttpResultFactory(ILogManager logManager, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IXmlSerializer xmlSerializer)
{
_fileSystem = fileSystem;
_jsonSerializer = jsonSerializer;
_xmlSerializer = xmlSerializer;
_logger = logManager.GetLogger("HttpResultFactory");
}
@@ -130,7 +136,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
throw new ArgumentNullException("result");
}
var optimizedResult = requestContext.ToOptimizedResult(result);
var optimizedResult = ToOptimizedResult(requestContext, result);
if (responseHeaders == null)
{
@@ -152,7 +158,99 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return optimizedResult;
}
public static string GetCompressionType(IRequest request)
{
var prefs = new RequestPreferences(request);
if (prefs.AcceptsDeflate)
return "deflate";
if (prefs.AcceptsGzip)
return "gzip";
return null;
}
/// <summary>
/// Returns the optimized result for the IRequestContext.
/// Does not use or store results in any cache.
/// </summary>
/// <param name="request"></param>
/// <param name="dto"></param>
/// <returns></returns>
public object ToOptimizedResult<T>(IRequest request, T dto)
{
request.Response.Dto = dto;
var compressionType = GetCompressionType(request);
if (compressionType == null)
{
var contentType = request.ResponseContentType;
var contentTypeAttr = ContentFormat.GetEndpointAttributes(contentType);
switch (contentTypeAttr)
{
case RequestAttributes.Xml:
return SerializeToXmlString(dto);
case RequestAttributes.Json:
return _jsonSerializer.SerializeToString(dto);
}
}
using (var ms = new MemoryStream())
{
using (var compressionStream = GetCompressionStream(ms, compressionType))
{
ContentTypes.Instance.SerializeToStream(request, dto, compressionStream);
compressionStream.Close();
var compressedBytes = ms.ToArray();
var httpResult = new HttpResult(compressedBytes, request.ResponseContentType)
{
Status = request.Response.StatusCode
};
httpResult.Headers["Content-Length"] = compressedBytes.Length.ToString(UsCulture);
httpResult.Headers["Content-Encoding"] = compressionType;
return httpResult;
}
}
}
public static string SerializeToXmlString(object from)
{
using (var ms = new MemoryStream())
{
var xwSettings = new XmlWriterSettings();
xwSettings.Encoding = new UTF8Encoding(false);
xwSettings.OmitXmlDeclaration = false;
using (var xw = XmlWriter.Create(ms, xwSettings))
{
var serializer = new DataContractSerializer(from.GetType());
serializer.WriteObject(xw, from);
xw.Flush();
ms.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(ms);
return reader.ReadToEnd();
}
}
}
private static Stream GetCompressionStream(Stream outputStream, string compressionType)
{
if (compressionType == "deflate")
return new DeflateStream(outputStream, CompressionMode.Compress);
if (compressionType == "gzip")
return new GZipStream(outputStream, CompressionMode.Compress);
throw new NotSupportedException(compressionType);
}
/// <summary>
/// Gets the optimized result using cache.
/// </summary>
@@ -471,7 +569,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
var contentType = options.ContentType;
var responseHeaders = options.ResponseHeaders;
var requestedCompressionType = requestContext.GetCompressionType();
var requestedCompressionType = GetCompressionType(requestContext);
if (!compress || string.IsNullOrEmpty(requestedCompressionType))
{
@@ -513,16 +611,64 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
}
var contents = content.Compress(requestedCompressionType);
var contents = Compress(content, requestedCompressionType);
responseHeaders["Content-Length"] = contents.Length.ToString(UsCulture);
responseHeaders["Content-Encoding"] = requestedCompressionType;
if (isHeadRequest)
{
return GetHttpResult(new byte[] { }, contentType);
}
return new CompressedResult(contents, requestedCompressionType, contentType);
return GetHttpResult(contents, contentType, responseHeaders);
}
public static byte[] Compress(string text, string compressionType)
{
if (compressionType == "deflate")
return Deflate(text);
if (compressionType == "gzip")
return GZip(text);
throw new NotSupportedException(compressionType);
}
public static byte[] Deflate(string text)
{
return Deflate(Encoding.UTF8.GetBytes(text));
}
public static 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.Close();
return ms.ToArray();
}
}
public static byte[] GZip(string text)
{
return GZip(Encoding.UTF8.GetBytes(text));
}
public static byte[] GZip(byte[] buffer)
{
using (var ms = new MemoryStream())
using (var zipStream = new GZipStream(ms, CompressionMode.Compress))
{
zipStream.Write(buffer, 0, buffer.Length);
zipStream.Close();
return ms.ToArray();
}
}
/// <summary>