mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-07 02:36:20 +00:00
update file responses
This commit is contained in:
@@ -228,7 +228,8 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
_streamFactory,
|
||||
_enableDualModeSockets,
|
||||
GetRequest,
|
||||
_fileSystem);
|
||||
_fileSystem,
|
||||
_environment);
|
||||
}
|
||||
|
||||
private IHttpRequest GetRequest(HttpListenerContext httpContext)
|
||||
@@ -452,6 +453,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
var date = DateTime.Now;
|
||||
var httpRes = httpReq.Response;
|
||||
bool enableLog = false;
|
||||
bool logHeaders = false;
|
||||
string urlToLog = null;
|
||||
string remoteIp = null;
|
||||
|
||||
@@ -490,13 +492,14 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
var urlString = url.OriginalString;
|
||||
enableLog = EnableLogging(urlString, localPath);
|
||||
urlToLog = urlString;
|
||||
logHeaders = enableLog && urlToLog.IndexOf("/videos/", StringComparison.OrdinalIgnoreCase) != -1;
|
||||
|
||||
if (enableLog)
|
||||
{
|
||||
urlToLog = GetUrlToLog(urlString);
|
||||
remoteIp = httpReq.RemoteIp;
|
||||
|
||||
LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent);
|
||||
LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent, logHeaders ? httpReq.Headers : null);
|
||||
}
|
||||
|
||||
if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) ||
|
||||
@@ -611,7 +614,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
|
||||
var duration = DateTime.Now - date;
|
||||
|
||||
LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration);
|
||||
LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration, logHeaders ? httpRes.Headers : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,31 +353,28 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// <summary>
|
||||
/// Pres the process optimized result.
|
||||
/// </summary>
|
||||
/// <param name="requestContext">The request context.</param>
|
||||
/// <param name="responseHeaders">The responseHeaders.</param>
|
||||
/// <param name="cacheKey">The cache key.</param>
|
||||
/// <param name="cacheKeyString">The cache key string.</param>
|
||||
/// <param name="lastDateModified">The last date modified.</param>
|
||||
/// <param name="cacheDuration">Duration of the cache.</param>
|
||||
/// <param name="contentType">Type of the content.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType)
|
||||
{
|
||||
responseHeaders["ETag"] = string.Format("\"{0}\"", cacheKeyString);
|
||||
|
||||
if (IsNotModified(requestContext, cacheKey, lastDateModified, cacheDuration))
|
||||
var noCache = (requestContext.Headers.Get("Cache-Control") ?? string.Empty).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
|
||||
|
||||
if (!noCache)
|
||||
{
|
||||
AddAgeHeader(responseHeaders, lastDateModified);
|
||||
AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration);
|
||||
if (IsNotModified(requestContext, cacheKey, lastDateModified, cacheDuration))
|
||||
{
|
||||
AddAgeHeader(responseHeaders, lastDateModified);
|
||||
AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration, noCache);
|
||||
|
||||
var result = new HttpResult(new byte[] { }, contentType ?? "text/html", HttpStatusCode.NotModified);
|
||||
var result = new HttpResult(new byte[] { }, contentType ?? "text/html", HttpStatusCode.NotModified);
|
||||
|
||||
AddResponseHeaders(result, responseHeaders);
|
||||
AddResponseHeaders(result, responseHeaders);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
AddCachingHeaders(responseHeaders, cacheKeyString, lastDateModified, cacheDuration);
|
||||
AddCachingHeaders(responseHeaders, cacheKeyString, lastDateModified, cacheDuration, noCache);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -673,11 +670,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// <summary>
|
||||
/// Adds the caching responseHeaders.
|
||||
/// </summary>
|
||||
/// <param name="responseHeaders">The responseHeaders.</param>
|
||||
/// <param name="cacheKey">The cache key.</param>
|
||||
/// <param name="lastDateModified">The last date modified.</param>
|
||||
/// <param name="cacheDuration">Duration of the cache.</param>
|
||||
private void AddCachingHeaders(IDictionary<string, string> responseHeaders, string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration)
|
||||
private void AddCachingHeaders(IDictionary<string, string> responseHeaders, string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, bool noCache)
|
||||
{
|
||||
// Don't specify both last modified and Etag, unless caching unconditionally. They are redundant
|
||||
// https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching
|
||||
@@ -687,11 +680,11 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
responseHeaders["Last-Modified"] = lastDateModified.Value.ToString("r");
|
||||
}
|
||||
|
||||
if (cacheDuration.HasValue)
|
||||
if (!noCache && cacheDuration.HasValue)
|
||||
{
|
||||
responseHeaders["Cache-Control"] = "public, max-age=" + Convert.ToInt32(cacheDuration.Value.TotalSeconds);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(cacheKey))
|
||||
else if (!noCache && !string.IsNullOrEmpty(cacheKey))
|
||||
{
|
||||
responseHeaders["Cache-Control"] = "public";
|
||||
}
|
||||
@@ -701,18 +694,15 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
responseHeaders["pragma"] = "no-cache, no-store, must-revalidate";
|
||||
}
|
||||
|
||||
AddExpiresHeader(responseHeaders, cacheKey, cacheDuration);
|
||||
AddExpiresHeader(responseHeaders, cacheKey, cacheDuration, noCache);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the expires header.
|
||||
/// </summary>
|
||||
/// <param name="responseHeaders">The responseHeaders.</param>
|
||||
/// <param name="cacheKey">The cache key.</param>
|
||||
/// <param name="cacheDuration">Duration of the cache.</param>
|
||||
private void AddExpiresHeader(IDictionary<string, string> responseHeaders, string cacheKey, TimeSpan? cacheDuration)
|
||||
private void AddExpiresHeader(IDictionary<string, string> responseHeaders, string cacheKey, TimeSpan? cacheDuration, bool noCache)
|
||||
{
|
||||
if (cacheDuration.HasValue)
|
||||
if (!noCache && cacheDuration.HasValue)
|
||||
{
|
||||
responseHeaders["Expires"] = DateTime.UtcNow.Add(cacheDuration.Value).ToString("r");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Services;
|
||||
using SocketHttpListener.Net;
|
||||
|
||||
namespace Emby.Server.Implementations.HttpServer
|
||||
@@ -19,9 +21,18 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
logger.Info("{0} {1}. UserAgent: {2}", request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, url, request.UserAgent ?? string.Empty);
|
||||
}
|
||||
|
||||
public static void LogRequest(ILogger logger, string url, string method, string userAgent)
|
||||
public static void LogRequest(ILogger logger, string url, string method, string userAgent, QueryParamCollection headers)
|
||||
{
|
||||
logger.Info("{0} {1}. UserAgent: {2}", "HTTP " + method, url, userAgent ?? string.Empty);
|
||||
if (headers == null)
|
||||
{
|
||||
logger.Info("{0} {1}. UserAgent: {2}", "HTTP " + method, url, userAgent ?? string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
var headerText = string.Join(", ", headers.Select(i => i.Name + "=" + i.Value).ToArray());
|
||||
|
||||
logger.Info("HTTP {0} {1}. {2}", method, url, headerText);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -32,12 +43,13 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="endPoint">The end point.</param>
|
||||
/// <param name="duration">The duration.</param>
|
||||
public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration)
|
||||
public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration, QueryParamCollection headers)
|
||||
{
|
||||
var durationMs = duration.TotalMilliseconds;
|
||||
var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms";
|
||||
|
||||
logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url);
|
||||
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());
|
||||
logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4} {5}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url, headerText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using MediaBrowser.Model.Cryptography;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Net;
|
||||
using MediaBrowser.Model.Services;
|
||||
using MediaBrowser.Model.System;
|
||||
using MediaBrowser.Model.Text;
|
||||
using SocketHttpListener.Primitives;
|
||||
|
||||
@@ -30,8 +31,9 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly Func<HttpListenerContext, IHttpRequest> _httpRequestFactory;
|
||||
private readonly bool _enableDualMode;
|
||||
private readonly IEnvironmentInfo _environment;
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
_logger = logger;
|
||||
_certificate = certificate;
|
||||
@@ -44,6 +46,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
|
||||
_enableDualMode = enableDualMode;
|
||||
_httpRequestFactory = httpRequestFactory;
|
||||
_fileSystem = fileSystem;
|
||||
_environment = environment;
|
||||
}
|
||||
|
||||
public Action<Exception, IRequest, bool> ErrorHandler { get; set; }
|
||||
@@ -56,7 +59,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);
|
||||
_listener = new HttpListener(_logger, _cryptoProvider, _streamFactory, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider, _fileSystem, _environment);
|
||||
|
||||
_listener.EnableDualMode = _enableDualMode;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Model.Services;
|
||||
using SocketHttpListener.Net;
|
||||
using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse;
|
||||
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
|
||||
@@ -66,6 +67,14 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
|
||||
_response.AddHeader(name, value);
|
||||
}
|
||||
|
||||
public QueryParamCollection Headers
|
||||
{
|
||||
get
|
||||
{
|
||||
return _response.Headers;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetHeader(string name)
|
||||
{
|
||||
return _response.Headers[name];
|
||||
|
||||
Reference in New Issue
Block a user