mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-05-27 02:56:54 +01:00
Merge
This commit is contained in:
@@ -2,17 +2,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.ComponentModel.Composition.Hosting;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Logging;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Common.Serialization;
|
||||
using MediaBrowser.Model.Progress;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Common.Kernel
|
||||
{
|
||||
@@ -93,6 +92,8 @@ namespace MediaBrowser.Common.Kernel
|
||||
/// </summary>
|
||||
protected void ReloadComposableParts()
|
||||
{
|
||||
DisposeComposableParts();
|
||||
|
||||
// Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that
|
||||
// This will prevent the .dll file from getting locked, and allow us to replace it when needed
|
||||
IEnumerable<Assembly> pluginAssemblies = Directory.GetFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.AllDirectories).Select(f => Assembly.Load(File.ReadAllBytes((f))));
|
||||
@@ -203,10 +204,33 @@ namespace MediaBrowser.Common.Kernel
|
||||
/// </summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
DisposeComposableParts();
|
||||
DisposeHttpServer();
|
||||
DisposeLogger();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes all objects gathered through MEF composable parts
|
||||
/// </summary>
|
||||
protected virtual void DisposeComposableParts()
|
||||
{
|
||||
DisposePlugins();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes all plugins
|
||||
/// </summary>
|
||||
private void DisposePlugins()
|
||||
{
|
||||
if (Plugins != null)
|
||||
{
|
||||
foreach (BasePlugin plugin in Plugins)
|
||||
{
|
||||
plugin.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the current HttpServer
|
||||
/// </summary>
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
|
||||
protected string ResourcePath { get; set; }
|
||||
|
||||
public override string ContentType
|
||||
public override Task<string> GetContentType()
|
||||
{
|
||||
get
|
||||
return Task.Run(() =>
|
||||
{
|
||||
string extension = Path.GetExtension(ResourcePath);
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
}
|
||||
|
||||
return "text/plain; charset=utf-8";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override Task WriteResponseToOutputStream(Stream stream)
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
/// <summary>
|
||||
/// Gets the MIME type to include in the response headers
|
||||
/// </summary>
|
||||
public abstract string ContentType { get; }
|
||||
public abstract Task<string> GetContentType();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status code to include in the response headers
|
||||
@@ -129,31 +129,9 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
}
|
||||
}
|
||||
|
||||
private bool _LastDateModifiedDiscovered = false;
|
||||
private DateTime? _LastDateModified = null;
|
||||
/// <summary>
|
||||
/// Gets the last date modified of the content being returned, if this can be determined.
|
||||
/// This will be used to invalidate the cache, so it's not needed if CacheDuration is 0.
|
||||
/// </summary>
|
||||
public DateTime? LastDateModified
|
||||
public virtual bool ShouldCompressResponse(string contentType)
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_LastDateModifiedDiscovered)
|
||||
{
|
||||
_LastDateModified = GetLastDateModified();
|
||||
}
|
||||
|
||||
return _LastDateModified;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool CompressResponse
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ClientSupportsCompression
|
||||
@@ -207,10 +185,12 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
// When serving a range request, we need to return status code 206 to indicate a partial response body
|
||||
StatusCode = SupportsByteRangeRequests && IsRangeRequest ? 206 : 200;
|
||||
|
||||
ctx.Response.ContentType = ContentType;
|
||||
ctx.Response.ContentType = await GetContentType();
|
||||
|
||||
TimeSpan cacheDuration = CacheDuration;
|
||||
|
||||
DateTime? lastDateModified = await GetLastDateModified();
|
||||
|
||||
if (ctx.Request.Headers.AllKeys.Contains("If-Modified-Since"))
|
||||
{
|
||||
DateTime ifModifiedSince;
|
||||
@@ -218,18 +198,20 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
if (DateTime.TryParse(ctx.Request.Headers["If-Modified-Since"].Replace(" GMT", string.Empty), out ifModifiedSince))
|
||||
{
|
||||
// If the cache hasn't expired yet just return a 304
|
||||
if (IsCacheValid(ifModifiedSince, cacheDuration, LastDateModified))
|
||||
if (IsCacheValid(ifModifiedSince, cacheDuration, lastDateModified))
|
||||
{
|
||||
StatusCode = 304;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PrepareResponse();
|
||||
await PrepareResponse();
|
||||
|
||||
if (IsResponseValid)
|
||||
{
|
||||
await ProcessUncachedRequest(ctx, cacheDuration);
|
||||
bool compressResponse = ShouldCompressResponse(ctx.Response.ContentType) && ClientSupportsCompression;
|
||||
|
||||
await ProcessUncachedRequest(ctx, compressResponse, cacheDuration, lastDateModified);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -241,7 +223,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
{
|
||||
// It might be too late if some response data has already been transmitted, but try to set this
|
||||
ctx.Response.StatusCode = 500;
|
||||
|
||||
|
||||
Logger.LogException(ex);
|
||||
}
|
||||
finally
|
||||
@@ -250,7 +232,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessUncachedRequest(HttpListenerContext ctx, TimeSpan cacheDuration)
|
||||
private async Task ProcessUncachedRequest(HttpListenerContext ctx, bool compressResponse, TimeSpan cacheDuration, DateTime? lastDateModified)
|
||||
{
|
||||
long? totalContentLength = TotalContentLength;
|
||||
|
||||
@@ -270,7 +252,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
}
|
||||
|
||||
// Add the compression header
|
||||
if (CompressResponse && ClientSupportsCompression)
|
||||
if (compressResponse)
|
||||
{
|
||||
ctx.Response.AddHeader("Content-Encoding", CompressionMethod);
|
||||
}
|
||||
@@ -278,7 +260,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
// Add caching headers
|
||||
if (cacheDuration.Ticks > 0)
|
||||
{
|
||||
CacheResponse(ctx.Response, cacheDuration, LastDateModified);
|
||||
CacheResponse(ctx.Response, cacheDuration, lastDateModified);
|
||||
}
|
||||
|
||||
// Set the status code
|
||||
@@ -289,7 +271,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
// Finally, write the response data
|
||||
Stream outputStream = ctx.Response.OutputStream;
|
||||
|
||||
if (CompressResponse && ClientSupportsCompression)
|
||||
if (compressResponse)
|
||||
{
|
||||
if (CompressionMethod.Equals("deflate", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -321,10 +303,11 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gives subclasses a chance to do and prep work, and also to validate data and set an error status code, if needed
|
||||
/// Gives subclasses a chance to do any prep work, and also to validate data and set an error status code, if needed
|
||||
/// </summary>
|
||||
protected virtual void PrepareResponse()
|
||||
protected virtual Task PrepareResponse()
|
||||
{
|
||||
return Task.Run(() => { });
|
||||
}
|
||||
|
||||
protected abstract Task WriteResponseToOutputStream(Stream stream);
|
||||
@@ -372,9 +355,11 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
return null;
|
||||
}
|
||||
|
||||
protected virtual DateTime? GetLastDateModified()
|
||||
protected virtual Task<DateTime?> GetLastDateModified()
|
||||
{
|
||||
return null;
|
||||
DateTime? value = null;
|
||||
|
||||
return Task.Run<DateTime?>(() => { return value; });
|
||||
}
|
||||
|
||||
private bool IsResponseValid
|
||||
|
||||
@@ -6,19 +6,22 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
{
|
||||
public abstract class BaseJsonHandler<T> : BaseHandler
|
||||
{
|
||||
public override string ContentType
|
||||
public override Task<string> GetContentType()
|
||||
{
|
||||
get { return MimeTypes.JsonMimeType; }
|
||||
return Task.Run(() =>
|
||||
{
|
||||
return MimeTypes.JsonMimeType;
|
||||
});
|
||||
}
|
||||
|
||||
private bool _ObjectToSerializeEnsured = false;
|
||||
private T _ObjectToSerialize;
|
||||
|
||||
private void EnsureObjectToSerialize()
|
||||
private async Task EnsureObjectToSerialize()
|
||||
{
|
||||
if (!_ObjectToSerializeEnsured)
|
||||
{
|
||||
_ObjectToSerialize = GetObjectToSerialize();
|
||||
_ObjectToSerialize = await GetObjectToSerialize();
|
||||
|
||||
if (_ObjectToSerialize == null)
|
||||
{
|
||||
@@ -29,30 +32,18 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
}
|
||||
}
|
||||
|
||||
private T ObjectToSerialize
|
||||
protected abstract Task<T> GetObjectToSerialize();
|
||||
|
||||
protected override async Task PrepareResponse()
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureObjectToSerialize();
|
||||
return _ObjectToSerialize;
|
||||
}
|
||||
await EnsureObjectToSerialize();
|
||||
}
|
||||
|
||||
protected abstract T GetObjectToSerialize();
|
||||
|
||||
protected override void PrepareResponse()
|
||||
protected async override Task WriteResponseToOutputStream(Stream stream)
|
||||
{
|
||||
base.PrepareResponse();
|
||||
await EnsureObjectToSerialize();
|
||||
|
||||
EnsureObjectToSerialize();
|
||||
}
|
||||
|
||||
protected override Task WriteResponseToOutputStream(Stream stream)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
JsonSerializer.SerializeToStream<T>(ObjectToSerialize, stream);
|
||||
});
|
||||
JsonSerializer.SerializeToStream<T>(_ObjectToSerialize, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,27 +77,22 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CompressResponse
|
||||
public override bool ShouldCompressResponse(string contentType)
|
||||
{
|
||||
get
|
||||
// Can't compress these
|
||||
if (IsRangeRequest)
|
||||
{
|
||||
// Can't compress these
|
||||
if (IsRangeRequest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string contentType = ContentType;
|
||||
|
||||
// Don't compress media
|
||||
if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// It will take some work to support compression within this handler
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't compress media
|
||||
if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// It will take some work to support compression within this handler
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override long? GetTotalContentLength()
|
||||
@@ -105,31 +100,32 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||
return SourceStream.Length;
|
||||
}
|
||||
|
||||
protected override DateTime? GetLastDateModified()
|
||||
protected override Task<DateTime?> GetLastDateModified()
|
||||
{
|
||||
EnsureSourceStream();
|
||||
|
||||
if (SourceStream == null)
|
||||
return Task.Run<DateTime?>(() =>
|
||||
{
|
||||
return null;
|
||||
}
|
||||
EnsureSourceStream();
|
||||
|
||||
return File.GetLastWriteTime(Path);
|
||||
if (SourceStream == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return File.GetLastWriteTime(Path);
|
||||
});
|
||||
}
|
||||
|
||||
public override string ContentType
|
||||
public override Task<string> GetContentType()
|
||||
{
|
||||
get
|
||||
return Task.Run(() =>
|
||||
{
|
||||
return MimeTypes.GetMimeType(Path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override void PrepareResponse()
|
||||
protected override Task PrepareResponse()
|
||||
{
|
||||
base.PrepareResponse();
|
||||
|
||||
EnsureSourceStream();
|
||||
return Task.Run(() => { EnsureSourceStream(); });
|
||||
}
|
||||
|
||||
protected async override Task WriteResponseToOutputStream(Stream stream)
|
||||
|
||||
Reference in New Issue
Block a user