Switch to HeaderNames instead of hardcoded strings (and other header related fixes)

This commit is contained in:
Claus Vium 2019-03-05 19:20:28 +01:00
parent 318e0d4a24
commit 78742b8e4c
15 changed files with 82 additions and 119 deletions

View File

@ -15,6 +15,7 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpClientManager
{
@ -179,11 +180,11 @@ namespace Emby.Server.Implementations.HttpClientManager
foreach (var header in options.RequestHeaders)
{
if (string.Equals(header.Key, "Accept", StringComparison.OrdinalIgnoreCase))
if (string.Equals(header.Key, HeaderNames.Accept, StringComparison.OrdinalIgnoreCase))
{
request.Accept = header.Value;
}
else if (string.Equals(header.Key, "User-Agent", StringComparison.OrdinalIgnoreCase))
else if (string.Equals(header.Key, HeaderNames.UserAgent, StringComparison.OrdinalIgnoreCase))
{
SetUserAgent(request, header.Value);
hasUserAgent = true;

View File

@ -9,6 +9,7 @@ using Emby.Server.Implementations.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer
{
@ -56,10 +57,10 @@ namespace Emby.Server.Implementations.HttpServer
FileSystem = fileSystem;
RangeHeader = rangeHeader;
Headers["Content-Type"] = contentType;
Headers[HeaderNames.ContentType] = contentType;
TotalContentLength = fileSystem.GetFileInfo(path).Length;
Headers["Accept-Ranges"] = "bytes";
Headers[HeaderNames.AcceptRanges] = "bytes";
if (string.IsNullOrWhiteSpace(rangeHeader))
{
@ -97,8 +98,8 @@ namespace Emby.Server.Implementations.HttpServer
// Content-Length is the length of what we're serving, not the original content
var lengthString = RangeLength.ToString(UsCulture);
var rangeString = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
Headers["Content-Range"] = rangeString;
var rangeString = $"bytes {RangeStart}-{RangeEnd}/{TotalContentLength}";
Headers[HeaderNames.ContentRange] = rangeString;
Logger.LogInformation("Setting range response values for {0}. RangeRequest: {1} Content-Length: {2}, Content-Range: {3}", Path, RangeHeader, lengthString, rangeString);
}

View File

@ -75,7 +75,7 @@ namespace Emby.Server.Implementations.HttpServer
public object GetRedirectResult(string url)
{
var responseHeaders = new Dictionary<string, string>();
responseHeaders["Location"] = url;
responseHeaders[HeaderNames.Location] = url;
var result = new HttpResult(Array.Empty<byte>(), "text/plain", HttpStatusCode.Redirect);
@ -96,9 +96,9 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders = new Dictionary<string, string>();
}
if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string expires))
if (addCachePrevention && !responseHeaders.TryGetValue(HeaderNames.Expires, out string expires))
{
responseHeaders["Expires"] = "-1";
responseHeaders[HeaderNames.Expires] = "-1";
}
AddResponseHeaders(result, responseHeaders);
@ -142,9 +142,9 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders = new Dictionary<string, string>();
}
if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string _))
if (addCachePrevention && !responseHeaders.TryGetValue(HeaderNames.Expires, out string _))
{
responseHeaders["Expires"] = "-1";
responseHeaders[HeaderNames.Expires] = "-1";
}
AddResponseHeaders(result, responseHeaders);
@ -186,9 +186,9 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders = new Dictionary<string, string>();
}
if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string _))
if (addCachePrevention && !responseHeaders.TryGetValue(HeaderNames.Expires, out string _))
{
responseHeaders["Expires"] = "-1";
responseHeaders[HeaderNames.Expires] = "-1";
}
AddResponseHeaders(result, responseHeaders);
@ -213,7 +213,7 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
responseHeaders["Expires"] = "-1";
responseHeaders[HeaderNames.Expires] = "-1";
return ToOptimizedResultInternal(requestContext, result, responseHeaders);
}
@ -245,7 +245,7 @@ namespace Emby.Server.Implementations.HttpServer
private static string GetCompressionType(IRequest request)
{
var acceptEncoding = request.Headers["Accept-Encoding"].ToString();
var acceptEncoding = request.Headers[HeaderNames.AcceptEncoding].ToString();
if (string.IsNullOrEmpty(acceptEncoding))
{
@ -325,9 +325,9 @@ namespace Emby.Server.Implementations.HttpServer
}
content = Compress(content, requestedCompressionType);
responseHeaders["Content-Encoding"] = requestedCompressionType;
responseHeaders[HeaderNames.ContentEncoding] = requestedCompressionType;
responseHeaders["Vary"] = "Accept-Encoding";
responseHeaders[HeaderNames.Vary] = HeaderNames.AcceptEncoding;
var contentLength = content.Length;
@ -537,7 +537,7 @@ namespace Emby.Server.Implementations.HttpServer
AddCachingHeaders(responseHeaders, options.CacheDuration, false, options.DateLastModified);
AddAgeHeader(responseHeaders, options.DateLastModified);
var rangeHeader = requestContext.Headers["Range"];
var rangeHeader = requestContext.Headers[HeaderNames.Range];
if (!isHeadRequest && !string.IsNullOrEmpty(options.Path))
{
@ -606,23 +606,23 @@ namespace Emby.Server.Implementations.HttpServer
{
if (noCache)
{
responseHeaders["Cache-Control"] = "no-cache, no-store, must-revalidate";
responseHeaders["pragma"] = "no-cache, no-store, must-revalidate";
responseHeaders[HeaderNames.CacheControl] = "no-cache, no-store, must-revalidate";
responseHeaders[HeaderNames.Pragma] = "no-cache, no-store, must-revalidate";
return;
}
if (cacheDuration.HasValue)
{
responseHeaders["Cache-Control"] = "public, max-age=" + cacheDuration.Value.TotalSeconds;
responseHeaders[HeaderNames.CacheControl] = "public, max-age=" + cacheDuration.Value.TotalSeconds;
}
else
{
responseHeaders["Cache-Control"] = "public";
responseHeaders[HeaderNames.CacheControl] = "public";
}
if (lastModifiedDate.HasValue)
{
responseHeaders["Last-Modified"] = lastModifiedDate.ToString();
responseHeaders[HeaderNames.LastModified] = lastModifiedDate.ToString();
}
}
@ -635,7 +635,7 @@ namespace Emby.Server.Implementations.HttpServer
{
if (lastDateModified.HasValue)
{
responseHeaders["Age"] = Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture);
responseHeaders[HeaderNames.Age] = Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture);
}
}
@ -693,9 +693,4 @@ namespace Emby.Server.Implementations.HttpServer
}
}
}
public interface IBrotliCompressor
{
byte[] Compress(byte[] content);
}
}

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer
{
@ -66,8 +67,8 @@ namespace Emby.Server.Implementations.HttpServer
this._logger = logger;
ContentType = contentType;
Headers["Content-Type"] = contentType;
Headers["Accept-Ranges"] = "bytes";
Headers[HeaderNames.ContentType] = contentType;
Headers[HeaderNames.AcceptRanges] = "bytes";
StatusCode = HttpStatusCode.PartialContent;
SetRangeValues(contentLength);
@ -96,7 +97,7 @@ namespace Emby.Server.Implementations.HttpServer
RangeLength = 1 + RangeEnd - RangeStart;
// Content-Length is the length of what we're serving, not the original content
Headers["Content-Range"] = $"bytes {RangeStart}-{RangeEnd}/{TotalContentLength}";
Headers[HeaderNames.ContentRange] = $"bytes {RangeStart}-{RangeEnd}/{TotalContentLength}";
if (RangeStart > 0 && SourceStream.CanSeek)
{

View File

@ -3,6 +3,7 @@ using System.Globalization;
using System.Text;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer
{
@ -44,13 +45,13 @@ namespace Emby.Server.Implementations.HttpServer
if (dto is IHasHeaders hasHeaders)
{
if (!hasHeaders.Headers.ContainsKey("Server"))
if (!hasHeaders.Headers.ContainsKey(HeaderNames.Server))
{
hasHeaders.Headers["Server"] = "Microsoft-NetCore/2.0, UPnP/1.0 DLNADOC/1.50";
hasHeaders.Headers[HeaderNames.Server] = "Microsoft-NetCore/2.0, UPnP/1.0 DLNADOC/1.50";
}
// Content length has to be explicitly set on on HttpListenerResponse or it won't be happy
if (hasHeaders.Headers.TryGetValue("Content-Length", out string contentLength)
if (hasHeaders.Headers.TryGetValue(HeaderNames.ContentLength, out string contentLength)
&& !string.IsNullOrEmpty(contentLength))
{
var length = long.Parse(contentLength, UsCulture);

View File

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Security;
using MediaBrowser.Model.Services;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer.Security
{
@ -176,7 +177,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
if (string.IsNullOrEmpty(auth))
{
auth = httpReq.Headers["Authorization"];
auth = httpReq.Headers[HeaderNames.Authorization];
}
return GetAuthorization(auth);

View File

@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer
{
@ -52,7 +53,7 @@ namespace Emby.Server.Implementations.HttpServer
SourceStream = source;
Headers["Content-Type"] = contentType;
Headers[HeaderNames.ContentType] = contentType;
}
/// <summary>
@ -69,7 +70,7 @@ namespace Emby.Server.Implementations.HttpServer
SourceBytes = source;
Headers["Content-Type"] = contentType;
Headers[HeaderNames.ContentType] = contentType;
}
public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)

View File

@ -17,6 +17,7 @@ using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.LiveTv.Listings
{
@ -638,7 +639,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
#if NETSTANDARD2_0
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
options.RequestHeaders["Accept-Encoding"] = "deflate";
options.RequestHeaders[HeaderNames.AcceptEncoding] = "deflate";
}
#endif
@ -676,7 +677,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
#if NETSTANDARD2_0
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
options.RequestHeaders["Accept-Encoding"] = "deflate";
options.RequestHeaders[HeaderNames.AcceptEncoding] = "deflate";
}
#endif

View File

@ -19,6 +19,7 @@ using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.System;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.LiveTv.TunerHosts
{
@ -145,7 +146,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
if (protocol == MediaProtocol.Http)
{
// Use user-defined user-agent. If there isn't one, make it look like a browser.
httpHeaders["User-Agent"] = string.IsNullOrWhiteSpace(info.UserAgent) ?
httpHeaders[HeaderNames.UserAgent] = string.IsNullOrWhiteSpace(info.UserAgent) ?
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.85 Safari/537.36" :
info.UserAgent;
}

View File

@ -7,6 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.SocketSharp
{
@ -114,9 +115,9 @@ namespace Emby.Server.Implementations.SocketSharp
return form;
}
public string Accept => StringValues.IsNullOrEmpty(request.Headers["Accept"]) ? null : request.Headers["Accept"].ToString();
public string Accept => StringValues.IsNullOrEmpty(request.Headers[HeaderNames.Accept]) ? null : request.Headers[HeaderNames.Accept].ToString();
public string Authorization => StringValues.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"].ToString();
public string Authorization => StringValues.IsNullOrEmpty(request.Headers[HeaderNames.Authorization]) ? null : request.Headers[HeaderNames.Authorization].ToString();
protected bool validate_form { get; set; }
protected bool checked_form { get; set; }

View File

@ -18,6 +18,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace MediaBrowser.Api.Images
{
@ -634,7 +635,7 @@ namespace MediaBrowser.Api.Images
var imageResult = await _imageProcessor.ProcessImage(options).ConfigureAwait(false);
headers["Vary"] = "Accept";
headers[HeaderNames.Vary] = HeaderNames.Accept;
return await ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
{

View File

@ -29,6 +29,7 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
namespace MediaBrowser.Api.Library
{
@ -827,7 +828,7 @@ namespace MediaBrowser.Api.Library
var filename = (Path.GetFileName(path) ?? string.Empty).Replace("\"", string.Empty);
if (!string.IsNullOrWhiteSpace(filename))
{
headers["Content-Disposition"] = "attachment; filename=\"" + filename + "\"";
headers[HeaderNames.ContentDisposition] = "attachment; filename=\"" + filename + "\"";
}
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions

View File

@ -24,6 +24,7 @@ using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Services;
using MediaBrowser.Model.System;
using Microsoft.Net.Http.Headers;
namespace MediaBrowser.Api.LiveTv
{
@ -750,9 +751,10 @@ namespace MediaBrowser.Api.LiveTv
throw new FileNotFoundException();
}
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType(path);
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
[HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType(path)
};
return new ProgressiveFileCopier(_fileSystem, _streamHelper, path, outputHeaders, Logger, _environment)
{
@ -772,9 +774,10 @@ namespace MediaBrowser.Api.LiveTv
var directStreamProvider = liveStreamInfo;
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
outputHeaders["Content-Type"] = Model.Net.MimeTypes.GetMimeType("file." + request.Container);
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
[HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType("file." + request.Container)
};
return new ProgressiveFileCopier(directStreamProvider, _streamHelper, outputHeaders, Logger, _environment)
{

View File

@ -17,6 +17,7 @@ using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services;
using MediaBrowser.Model.System;
using Microsoft.Net.Http.Headers;
namespace MediaBrowser.Api.Playback.Progressive
{
@ -154,7 +155,7 @@ namespace MediaBrowser.Api.Playback.Progressive
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// TODO: Don't hardcode this
outputHeaders["Content-Type"] = MediaBrowser.Model.Net.MimeTypes.GetMimeType("file.ts");
outputHeaders[HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType("file.ts");
return new ProgressiveFileCopier(state.DirectStreamProvider, outputHeaders, null, Logger, EnvironmentInfo, CancellationToken.None)
{
@ -196,9 +197,11 @@ namespace MediaBrowser.Api.Playback.Progressive
{
if (state.MediaSource.IsInfiniteStream)
{
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
[HeaderNames.ContentType] = contentType
};
outputHeaders["Content-Type"] = contentType;
return new ProgressiveFileCopier(FileSystem, state.MediaPath, outputHeaders, null, Logger, EnvironmentInfo, CancellationToken.None)
{
@ -298,16 +301,16 @@ namespace MediaBrowser.Api.Playback.Progressive
if (trySupportSeek)
{
if (!string.IsNullOrWhiteSpace(Request.QueryString["Range"]))
if (!string.IsNullOrWhiteSpace(Request.QueryString[HeaderNames.Range]))
{
options.RequestHeaders["Range"] = Request.QueryString["Range"];
options.RequestHeaders[HeaderNames.Range] = Request.QueryString[HeaderNames.Range];
}
}
var response = await HttpClient.GetResponse(options).ConfigureAwait(false);
if (trySupportSeek)
{
foreach (var name in new[] { "Content-Range", "Accept-Ranges" })
foreach (var name in new[] { HeaderNames.ContentRange, HeaderNames.AcceptRanges })
{
var val = response.Headers[name];
if (!string.IsNullOrWhiteSpace(val))
@ -318,14 +321,7 @@ namespace MediaBrowser.Api.Playback.Progressive
}
else
{
responseHeaders["Accept-Ranges"] = "none";
}
// Seeing cases of -1 here
if (response.ContentLength.HasValue && response.ContentLength.Value >= 0)
{
// TODO
//responseHeaders["Content-Length"] = response.ContentLength.Value.ToString(UsCulture);
responseHeaders[HeaderNames.AcceptRanges] = "none";
}
if (isHeadRequest)
@ -338,7 +334,7 @@ namespace MediaBrowser.Api.Playback.Progressive
var result = new StaticRemoteStreamWriter(response);
result.Headers["Content-Type"] = response.ContentType;
result.Headers[HeaderNames.ContentType] = response.ContentType;
// Add the response headers to the result object
foreach (var header in responseHeaders)
@ -362,42 +358,14 @@ namespace MediaBrowser.Api.Playback.Progressive
// Use the command line args with a dummy playlist path
var outputPath = state.OutputFilePath;
responseHeaders["Accept-Ranges"] = "none";
responseHeaders[HeaderNames.AcceptRanges] = "none";
var contentType = state.GetMimeType(outputPath);
// TODO: The isHeadRequest is only here because ServiceStack will add Content-Length=0 to the response
// What we really want to do is hunt that down and remove that
var contentLength = state.EstimateContentLength || isHeadRequest ? GetEstimatedContentLength(state) : null;
if (contentLength.HasValue)
{
responseHeaders["Content-Length"] = contentLength.Value.ToString(UsCulture);
}
// Headers only
if (isHeadRequest)
{
var streamResult = ResultFactory.GetResult(null, new byte[] { }, contentType, responseHeaders);
var hasHeaders = streamResult as IHasHeaders;
if (hasHeaders != null)
{
// TODO
//if (contentLength.HasValue)
//{
// hasHeaders.Headers["Content-Length"] = contentLength.Value.ToString(CultureInfo.InvariantCulture);
//}
//else
//{
if (hasHeaders.Headers.ContainsKey("Content-Length"))
{
hasHeaders.Headers.Remove("Content-Length");
}
//}
}
return streamResult;
return ResultFactory.GetResult(null, new byte[] { }, contentType, responseHeaders);
}
var transcodingLock = ApiEntryPoint.Instance.GetTranscodingLock(outputPath);
@ -416,9 +384,11 @@ namespace MediaBrowser.Api.Playback.Progressive
state.Dispose();
}
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
var outputHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
[HeaderNames.ContentType] = contentType
};
outputHeaders["Content-Type"] = contentType;
// Add the response headers to the result object
foreach (var item in responseHeaders)
@ -433,22 +403,5 @@ namespace MediaBrowser.Api.Playback.Progressive
transcodingLock.Release();
}
}
/// <summary>
/// Gets the length of the estimated content.
/// </summary>
/// <param name="state">The state.</param>
/// <returns>System.Nullable{System.Int64}.</returns>
private long? GetEstimatedContentLength(StreamState state)
{
var totalBitrate = state.TotalOutputBitrate ?? 0;
if (totalBitrate > 0 && state.RunTimeTicks.HasValue)
{
return Convert.ToInt64(totalBitrate * TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds / 8);
}
return null;
}
}
}

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Net.Http.Headers;
namespace MediaBrowser.Common.Net
{
@ -24,8 +25,8 @@ namespace MediaBrowser.Common.Net
/// <value>The accept header.</value>
public string AcceptHeader
{
get => GetHeaderValue("Accept");
set => RequestHeaders["Accept"] = value;
get => GetHeaderValue(HeaderNames.Accept);
set => RequestHeaders[HeaderNames.Accept] = value;
}
/// <summary>
/// Gets or sets the cancellation token.
@ -45,8 +46,8 @@ namespace MediaBrowser.Common.Net
/// <value>The user agent.</value>
public string UserAgent
{
get => GetHeaderValue("User-Agent");
set => RequestHeaders["User-Agent"] = value;
get => GetHeaderValue(HeaderNames.UserAgent);
set => RequestHeaders[HeaderNames.UserAgent] = value;
}
/// <summary>