From dd078e7b8288277c4f01109966c20f794072bd3f Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 11:05:21 -0600 Subject: [PATCH 01/26] use named client --- Jellyfin.Api/Controllers/LiveTvController.cs | 3 ++- Jellyfin.Api/Controllers/RemoteImageController.cs | 3 ++- Jellyfin.Api/Controllers/VideosController.cs | 3 ++- Jellyfin.Api/Helpers/AudioHelper.cs | 3 ++- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs | 3 ++- .../Plugins/AudioDb/ArtistImageProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs | 5 +++-- MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs | 5 +++-- .../Plugins/TheTvdb/TvdbEpisodeImageProvider.cs | 3 ++- .../Plugins/TheTvdb/TvdbEpisodeProvider.cs | 3 ++- .../Plugins/TheTvdb/TvdbPersonImageProvider.cs | 3 ++- .../Plugins/TheTvdb/TvdbSeasonImageProvider.cs | 3 ++- .../Plugins/TheTvdb/TvdbSeriesImageProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs | 3 ++- .../Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs | 3 ++- .../Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs | 3 ++- .../Plugins/Tmdb/Movies/TmdbImageProvider.cs | 3 ++- .../Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 5 +++-- .../Plugins/Tmdb/People/TmdbPersonImageProvider.cs | 3 ++- .../Plugins/Tmdb/People/TmdbPersonProvider.cs | 3 ++- .../Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs | 3 ++- .../Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs | 3 ++- .../Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs | 3 ++- MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs | 3 ++- .../Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs | 3 ++- MediaBrowser.Providers/Studios/StudiosImageProvider.cs | 5 +++-- 32 files changed, 67 insertions(+), 36 deletions(-) diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 3ccfc826db..eace0f911c 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -16,6 +16,7 @@ using Jellyfin.Api.Models.LiveTvDtos; using Jellyfin.Data.Enums; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -1069,7 +1070,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetSchedulesDirectCountries() { - var client = _httpClientFactory.CreateClient(); + var client = _httpClientFactory.CreateClient(NamedClient.Default); // https://json.schedulesdirect.org/20141201/available/countries // Can't dispose the response as it's required up the call chain. var response = await client.GetAsync("https://json.schedulesdirect.org/20141201/available/countries") diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 30a4f73fc0..81aefd15cc 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Constants; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -244,7 +245,7 @@ namespace Jellyfin.Api.Controllers /// Task. private async Task DownloadImage(string url, Guid urlHash, string pointerCachePath) { - var httpClient = _httpClientFactory.CreateClient(); + var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); using var response = await httpClient.GetAsync(url).ConfigureAwait(false); var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last(); var fullCachePath = GetFullCachePath(urlHash + "." + ext); diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index f42810c945..bb03a8ded1 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -11,6 +11,7 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -470,7 +471,7 @@ namespace Jellyfin.Api.Controllers { StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager); - var httpClient = _httpClientFactory.CreateClient(); + var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, HttpContext).ConfigureAwait(false); } diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index eae2be05ba..a3f2d88ce5 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -138,7 +139,7 @@ namespace Jellyfin.Api.Helpers { StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); - var httpClient = _httpClientFactory.CreateClient(); + var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, _httpContextAccessor.HttpContext).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 155e8cb8ab..171b824ca6 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -156,7 +156,7 @@ namespace MediaBrowser.Providers.Manager /// public async Task SaveImage(BaseItem item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken) { - var httpClient = _httpClientFactory.CreateClient(); + var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); using var response = await httpClient.GetAsync(url, cancellationToken).ConfigureAwait(false); var contentType = response.Content.Headers.ContentType.MediaType; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs index c9dac9ecd8..e3a1decb88 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -96,7 +97,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb /// public Task GetImageResponse(string url, CancellationToken cancellationToken) { - var httpClient = _httpClientFactory.CreateClient(); + var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return httpClient.GetAsync(url, cancellationToken); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index 321144edf9..e6d89e6880 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; @@ -173,7 +174,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); - using var response = await _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs index 6512668681..54851c4d07 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -137,7 +138,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb public Task GetImageResponse(string url, CancellationToken cancellationToken) { - var httpClient = _httpClientFactory.CreateClient(); + var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return httpClient.GetAsync(url, cancellationToken); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index 708426500b..670c0cd05a 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; @@ -154,7 +155,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId); - using var response = await _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(path)); diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index 7f10e6922b..8414c93281 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -14,6 +14,7 @@ using System.Threading; using System.Threading.Tasks; using System.Xml; using MediaBrowser.Common; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -765,7 +766,7 @@ namespace MediaBrowser.Providers.Music _logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds); _stopWatchMusicBrainz.Restart(); - response = await _httpClientFactory.CreateClient().SendAsync(options).ConfigureAwait(false); + response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options).ConfigureAwait(false); // We retry a finite number of times, and only whilst MB is indicating 503 (throttling) } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs index c18725e0aa..8b8fea09e8 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -82,7 +83,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } public string Name => "The Open Movie Database"; diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 102ad82e17..d53eba7e94 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -9,6 +9,7 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -129,7 +130,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb var url = OmdbProvider.GetOmdbUrl(urlQuery); - using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); + using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var resultList = new List(); @@ -274,7 +275,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } class SearchResult diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index c45149c3a7..32dab60a6b 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -10,6 +10,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; @@ -296,7 +297,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb "i={0}&plot=short&tomatoes=true&r=json", imdbParam)); - using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); + using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var rootObject = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(path)); @@ -334,7 +335,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb imdbParam, seasonId)); - using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false); + using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var rootObject = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); Directory.CreateDirectory(Path.GetDirectoryName(path)); diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs index 4e7c0e5a60..de2f6875f8 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs @@ -6,6 +6,7 @@ using System.Net.Http; using System.Globalization; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; @@ -116,7 +117,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs index 90436c7c99..07167bda63 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; @@ -244,7 +245,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } public int Order => 0; diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs index 388a4e3e72..dc3c60dee0 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -106,7 +107,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb /// public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs index ff8c3455fa..49576d488d 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; @@ -148,7 +149,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs index d287828eb5..d96840e51c 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -146,7 +147,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs index c6dd8a5f3d..ca9b1d738f 100644 --- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -410,7 +411,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs index f434440283..f6592afe46 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Providers; @@ -155,7 +156,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs index 4da2c042f6..e627550f13 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs @@ -10,6 +10,7 @@ using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; @@ -271,7 +272,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs index 60d7a599ea..a975fb8f6a 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Providers; @@ -204,7 +205,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index d8918bb6b9..f8bc19395f 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -11,6 +11,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -383,7 +384,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies internal Task GetMovieDbResponse(HttpRequestMessage message) { message.Headers.UserAgent.ParseAdd(_appHost.ApplicationUserAgent); - return _httpClientFactory.CreateClient().SendAsync(message); + return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(message); } /// @@ -392,7 +393,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies /// public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs index f31a7faea2..ed478cac3a 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; @@ -129,7 +130,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs index e9fb5c7034..0ec79b3f28 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; @@ -259,7 +260,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs index 5705885b46..30b7674e33 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs @@ -7,6 +7,7 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; @@ -138,7 +139,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV protected Task GetResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs index 787514d05d..e7e2fd05b8 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; @@ -38,7 +39,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } public async Task> GetImages(BaseItem item, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs index e59504cc6d..73ed13267d 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs @@ -9,6 +9,7 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -124,7 +125,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } private async Task GetSeasonInfo(string seriesTmdbId, int season, string preferredMetadataLanguage, diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs index f11eeb15b3..125560175e 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; @@ -182,7 +183,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs index 0eded32330..aaba6ffc06 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs @@ -10,6 +10,7 @@ using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -551,7 +552,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs index 10374bde9e..25296387ba 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Providers; @@ -36,7 +37,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Trailers public Task GetImageResponse(string url, CancellationToken cancellationToken) { - return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken); } } } diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index 321153c6be..76dc7df7f7 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; @@ -122,7 +123,7 @@ namespace MediaBrowser.Providers.Studios public Task GetImageResponse(string url, CancellationToken cancellationToken) { - var httpClient = _httpClientFactory.CreateClient(); + var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); return httpClient.GetAsync(url, cancellationToken); } @@ -140,7 +141,7 @@ namespace MediaBrowser.Providers.Studios if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1) { - var httpClient = _httpClientFactory.CreateClient(); + var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); Directory.CreateDirectory(Path.GetDirectoryName(file)); await using var response = await httpClient.GetStreamAsync(url).ConfigureAwait(false); From 30ba35a33b1aa131bd5f3f3a82cf03b033f7f190 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 11:07:40 -0600 Subject: [PATCH 02/26] Use HttpClientFactory in SubtitleEncoder --- .../MediaBrowser.MediaEncoding.csproj | 1 + .../Subtitles/SubtitleEncoder.cs | 27 +++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 814edd7323..6ead93e09b 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,6 +24,7 @@ + diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 6ac5ac2ff1..0a9958b9eb 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -31,7 +32,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IMediaSourceManager _mediaSourceManager; /// @@ -46,7 +47,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, IMediaSourceManager mediaSourceManager) { _libraryManager = libraryManager; @@ -54,7 +55,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _appPaths = appPaths; _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _mediaSourceManager = mediaSourceManager; } @@ -750,24 +751,20 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - private Task GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken) + private async Task GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken) { switch (protocol) { case MediaProtocol.Http: - var opts = new HttpRequestOptions() - { - Url = path, - CancellationToken = cancellationToken, - - // Needed for seeking - BufferContent = true - }; - - return _httpClient.Get(opts); + { + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(path, cancellationToken) + .ConfigureAwait(false); + return await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + } case MediaProtocol.File: - return Task.FromResult(File.OpenRead(path)); + return File.OpenRead(path); default: throw new ArgumentOutOfRangeException(nameof(protocol)); } From 8215f15c452a313ab6b2d977f2c6369fa93d9e41 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 11:26:42 -0600 Subject: [PATCH 03/26] migrate to IHttpClientFactory in Emby.Dlna --- .../ConnectionManagerService.cs | 6 +- .../ContentDirectoryService.cs | 4 +- Emby.Dlna/Emby.Dlna.csproj | 1 + Emby.Dlna/Eventing/DlnaEventManager.cs | 30 ++--- Emby.Dlna/Main/DlnaEntryPoint.cs | 15 +-- .../MediaReceiverRegistrarService.cs | 6 +- Emby.Dlna/PlayTo/Device.cs | 41 ++++--- Emby.Dlna/PlayTo/PlayToManager.cs | 9 +- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 116 +++++++----------- Emby.Dlna/Service/BaseService.cs | 10 +- 10 files changed, 103 insertions(+), 135 deletions(-) diff --git a/Emby.Dlna/ConnectionManager/ConnectionManagerService.cs b/Emby.Dlna/ConnectionManager/ConnectionManagerService.cs index 12338e2b4b..f5a7eca720 100644 --- a/Emby.Dlna/ConnectionManager/ConnectionManagerService.cs +++ b/Emby.Dlna/ConnectionManager/ConnectionManagerService.cs @@ -1,8 +1,8 @@ #pragma warning disable CS1591 +using System.Net.Http; using System.Threading.Tasks; using Emby.Dlna.Service; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using Microsoft.Extensions.Logging; @@ -18,8 +18,8 @@ namespace Emby.Dlna.ConnectionManager IDlnaManager dlna, IServerConfigurationManager config, ILogger logger, - IHttpClient httpClient) - : base(logger, httpClient) + IHttpClientFactory httpClientFactory) + : base(logger, httpClientFactory) { _dlna = dlna; _config = config; diff --git a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs index 72732823ac..5760f260cf 100644 --- a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs +++ b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs @@ -2,11 +2,11 @@ using System; using System.Linq; +using System.Net.Http; using System.Threading.Tasks; using Emby.Dlna.Service; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; @@ -41,7 +41,7 @@ namespace Emby.Dlna.ContentDirectory IServerConfigurationManager config, IUserManager userManager, ILogger logger, - IHttpClient httpClient, + IHttpClientFactory httpClient, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 8538f580ca..6ed49944c0 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -80,6 +80,7 @@ + diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs index b66e966dff..fcc2aaa1e3 100644 --- a/Emby.Dlna/Eventing/DlnaEventManager.cs +++ b/Emby.Dlna/Eventing/DlnaEventManager.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net.Http; +using System.Net.Mime; using System.Text; using System.Threading.Tasks; using MediaBrowser.Common.Extensions; @@ -20,13 +21,13 @@ namespace Emby.Dlna.Eventing new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private readonly ILogger _logger; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - public DlnaEventManager(ILogger logger, IHttpClient httpClient) + public DlnaEventManager(ILogger logger, IHttpClientFactory httpClientFactory) { - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _logger = logger; } @@ -167,24 +168,17 @@ namespace Emby.Dlna.Eventing builder.Append(""); - var options = new HttpRequestOptions - { - RequestContent = builder.ToString(), - RequestContentType = "text/xml", - Url = subscription.CallbackUrl, - BufferContent = false - }; - - options.RequestHeaders.Add("NT", subscription.NotificationType); - options.RequestHeaders.Add("NTS", "upnp:propchange"); - options.RequestHeaders.Add("SID", subscription.Id); - options.RequestHeaders.Add("SEQ", subscription.TriggerCount.ToString(_usCulture)); + using var options = new HttpRequestMessage(new HttpMethod("NOTIFY"), subscription.CallbackUrl); + options.Content = new StringContent(builder.ToString(), Encoding.UTF8, MediaTypeNames.Text.Xml); + options.Headers.TryAddWithoutValidation("NT", subscription.NotificationType); + options.Headers.TryAddWithoutValidation("NTS", "upnp:propchange"); + options.Headers.TryAddWithoutValidation("SID", subscription.Id); + options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(_usCulture)); try { - using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false)) - { - } + await _httpClientFactory.CreateClient(NamedClient.Default) + .SendAsync(options).ConfigureAwait(false); } catch (OperationCanceledException) { diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 0ad82022dd..40c2cc0e0a 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -2,6 +2,7 @@ using System; using System.Globalization; +using System.Net.Http; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; @@ -36,7 +37,7 @@ namespace Emby.Dlna.Main private readonly ILogger _logger; private readonly IServerApplicationHost _appHost; private readonly ISessionManager _sessionManager; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDlnaManager _dlnaManager; @@ -61,7 +62,7 @@ namespace Emby.Dlna.Main ILoggerFactory loggerFactory, IServerApplicationHost appHost, ISessionManager sessionManager, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, @@ -79,7 +80,7 @@ namespace Emby.Dlna.Main _config = config; _appHost = appHost; _sessionManager = sessionManager; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _libraryManager = libraryManager; _userManager = userManager; _dlnaManager = dlnaManager; @@ -101,7 +102,7 @@ namespace Emby.Dlna.Main config, userManager, loggerFactory.CreateLogger(), - httpClient, + httpClientFactory, localizationManager, mediaSourceManager, userViewManager, @@ -112,11 +113,11 @@ namespace Emby.Dlna.Main dlnaManager, config, loggerFactory.CreateLogger(), - httpClient); + httpClientFactory); MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrarService( loggerFactory.CreateLogger(), - httpClient, + httpClientFactory, config); Current = this; } @@ -364,7 +365,7 @@ namespace Emby.Dlna.Main _appHost, _imageProcessor, _deviceDiscovery, - _httpClient, + _httpClientFactory, _config, _userDataManager, _localization, diff --git a/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarService.cs b/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarService.cs index 28de2fef52..e6d845e1e4 100644 --- a/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarService.cs +++ b/Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarService.cs @@ -1,8 +1,8 @@ #pragma warning disable CS1591 +using System.Net.Http; using System.Threading.Tasks; using Emby.Dlna.Service; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using Microsoft.Extensions.Logging; @@ -14,9 +14,9 @@ namespace Emby.Dlna.MediaReceiverRegistrar public MediaReceiverRegistrarService( ILogger logger, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, IServerConfigurationManager config) - : base(logger, httpClient) + : base(logger, httpClientFactory) { _config = config; } diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 5462e7abc5..c97acdb026 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Net.Http; using System.Security; using System.Threading; using System.Threading.Tasks; @@ -21,7 +22,7 @@ namespace Emby.Dlna.PlayTo { private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; @@ -34,10 +35,10 @@ namespace Emby.Dlna.PlayTo private int _connectFailureCount; private bool _disposed; - public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger) + public Device(DeviceInfo deviceProperties, IHttpClientFactory httpClientFactory, ILogger logger) { Properties = deviceProperties; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _logger = logger; } @@ -236,7 +237,7 @@ namespace Emby.Dlna.PlayTo _logger.LogDebug("Setting mute"); var value = mute ? 1 : 0; - await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value)) + await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value)) .ConfigureAwait(false); IsMuted = mute; @@ -271,7 +272,7 @@ namespace Emby.Dlna.PlayTo // Remote control will perform better Volume = value; - await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value)) + await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value)) .ConfigureAwait(false); } @@ -292,7 +293,7 @@ namespace Emby.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME")) + await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME")) .ConfigureAwait(false); RestartTimer(true); @@ -326,7 +327,7 @@ namespace Emby.Dlna.PlayTo } var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary); - await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header) + await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header) .ConfigureAwait(false); await Task.Delay(50).ConfigureAwait(false); @@ -368,7 +369,7 @@ namespace Emby.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - return new SsdpHttpClient(_httpClient).SendCommandAsync( + return new SsdpHttpClient(_httpClientFactory).SendCommandAsync( Properties.BaseUrl, service, command.Name, @@ -397,7 +398,7 @@ namespace Emby.Dlna.PlayTo var service = GetAvTransportService(); - await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1)) + await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1)) .ConfigureAwait(false); RestartTimer(true); @@ -415,7 +416,7 @@ namespace Emby.Dlna.PlayTo var service = GetAvTransportService(); - await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1)) + await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1)) .ConfigureAwait(false); TransportState = TransportState.Paused; @@ -542,7 +543,7 @@ namespace Emby.Dlna.PlayTo return; } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync( + var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync( Properties.BaseUrl, service, command.Name, @@ -592,7 +593,7 @@ namespace Emby.Dlna.PlayTo return; } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync( + var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync( Properties.BaseUrl, service, command.Name, @@ -625,7 +626,7 @@ namespace Emby.Dlna.PlayTo return null; } - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync( + var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync( Properties.BaseUrl, service, command.Name, @@ -667,7 +668,7 @@ namespace Emby.Dlna.PlayTo var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false); - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync( + var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync( Properties.BaseUrl, service, command.Name, @@ -734,7 +735,7 @@ namespace Emby.Dlna.PlayTo var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false); - var result = await new SsdpHttpClient(_httpClient).SendCommandAsync( + var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync( Properties.BaseUrl, service, command.Name, @@ -912,7 +913,7 @@ namespace Emby.Dlna.PlayTo string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl); - var httpClient = new SsdpHttpClient(_httpClient); + var httpClient = new SsdpHttpClient(_httpClientFactory); var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false); @@ -940,7 +941,7 @@ namespace Emby.Dlna.PlayTo string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl); - var httpClient = new SsdpHttpClient(_httpClient); + var httpClient = new SsdpHttpClient(_httpClientFactory); _logger.LogDebug("Dlna Device.GetRenderingProtocolAsync"); var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false); @@ -969,9 +970,9 @@ namespace Emby.Dlna.PlayTo return baseUrl + url; } - public static async Task CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, ILogger logger, CancellationToken cancellationToken) + public static async Task CreateuPnpDeviceAsync(Uri url, IHttpClientFactory httpClientFactory, ILogger logger, CancellationToken cancellationToken) { - var ssdpHttpClient = new SsdpHttpClient(httpClient); + var ssdpHttpClient = new SsdpHttpClient(httpClientFactory); var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false); @@ -1079,7 +1080,7 @@ namespace Emby.Dlna.PlayTo } } - return new Device(deviceProperties, httpClient, logger); + return new Device(deviceProperties, httpClientFactory, logger); } private static DeviceIcon CreateIcon(XElement element) diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index ff801f2630..3d1dd3e73f 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -4,6 +4,7 @@ using System; using System.Globalization; using System.Linq; using System.Net; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Events; @@ -33,7 +34,7 @@ namespace Emby.Dlna.PlayTo private readonly IDlnaManager _dlnaManager; private readonly IServerApplicationHost _appHost; private readonly IImageProcessor _imageProcessor; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IServerConfigurationManager _config; private readonly IUserDataManager _userDataManager; private readonly ILocalizationManager _localization; @@ -46,7 +47,7 @@ namespace Emby.Dlna.PlayTo private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1); private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); - public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder) + public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClientFactory httpClientFactory, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder) { _logger = logger; _sessionManager = sessionManager; @@ -56,7 +57,7 @@ namespace Emby.Dlna.PlayTo _appHost = appHost; _imageProcessor = imageProcessor; _deviceDiscovery = deviceDiscovery; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _config = config; _userDataManager = userDataManager; _localization = localization; @@ -174,7 +175,7 @@ namespace Emby.Dlna.PlayTo if (controller == null) { - var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _logger, cancellationToken).ConfigureAwait(false); + var device = await Device.CreateuPnpDeviceAsync(uri, _httpClientFactory, _logger, cancellationToken).ConfigureAwait(false); string deviceName = device.Properties.Name; diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index ab262bebfc..c6e9e074f1 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -4,6 +4,8 @@ using System; using System.Globalization; using System.IO; using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Mime; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -20,11 +22,11 @@ namespace Emby.Dlna.PlayTo private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; - public SsdpHttpClient(IHttpClient httpClient) + public SsdpHttpClient(IHttpClientFactory httpClientFactory) { - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; } public async Task SendCommandAsync( @@ -36,20 +38,18 @@ namespace Emby.Dlna.PlayTo CancellationToken cancellationToken = default) { var url = NormalizeServiceUrl(baseUrl, service.ControlUrl); - using (var response = await PostSoapDataAsync( - url, - $"\"{service.ServiceType}#{command}\"", - postData, - header, - cancellationToken) - .ConfigureAwait(false)) - using (var stream = response.Content) - using (var reader = new StreamReader(stream, Encoding.UTF8)) - { - return XDocument.Parse( - await reader.ReadToEndAsync().ConfigureAwait(false), - LoadOptions.PreserveWhitespace); - } + using var response = await PostSoapDataAsync( + url, + $"\"{service.ServiceType}#{command}\"", + postData, + header, + cancellationToken) + .ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + using var reader = new StreamReader(stream, Encoding.UTF8); + return XDocument.Parse( + await reader.ReadToEndAsync().ConfigureAwait(false), + LoadOptions.PreserveWhitespace); } private static string NormalizeServiceUrl(string baseUrl, string serviceUrl) @@ -76,49 +76,32 @@ namespace Emby.Dlna.PlayTo int eventport, int timeOut = 3600) { - var options = new HttpRequestOptions - { - Url = url, - UserAgent = USERAGENT, - LogErrorResponseBody = true, - BufferContent = false, - }; - - options.RequestHeaders["HOST"] = ip + ":" + port.ToString(_usCulture); - options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport.ToString(_usCulture) + ">"; - options.RequestHeaders["NT"] = "upnp:event"; - options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture); - - using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false)) - { - } + using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url); + options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT)); + options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture)); + options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">"); + options.Headers.TryAddWithoutValidation("NT", "upnp:event"); + options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture)); + + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .SendAsync(options) + .ConfigureAwait(false); } public async Task GetDataAsync(string url, CancellationToken cancellationToken) { - var options = new HttpRequestOptions - { - Url = url, - UserAgent = USERAGENT, - LogErrorResponseBody = true, - BufferContent = false, - - CancellationToken = cancellationToken - }; - - options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName; - - using (var response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false)) - using (var stream = response.Content) - using (var reader = new StreamReader(stream, Encoding.UTF8)) - { - return XDocument.Parse( - await reader.ReadToEndAsync().ConfigureAwait(false), - LoadOptions.PreserveWhitespace); - } + using var options = new HttpRequestMessage(HttpMethod.Get, url); + options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT)); + options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + using var reader = new StreamReader(stream, Encoding.UTF8); + return XDocument.Parse( + await reader.ReadToEndAsync().ConfigureAwait(false), + LoadOptions.PreserveWhitespace); } - private Task PostSoapDataAsync( + private Task PostSoapDataAsync( string url, string soapAction, string postData, @@ -130,29 +113,20 @@ namespace Emby.Dlna.PlayTo soapAction = $"\"{soapAction}\""; } - var options = new HttpRequestOptions - { - Url = url, - UserAgent = USERAGENT, - LogErrorResponseBody = true, - BufferContent = false, - - CancellationToken = cancellationToken - }; - - options.RequestHeaders["SOAPAction"] = soapAction; - options.RequestHeaders["Pragma"] = "no-cache"; - options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName; + using var options = new HttpRequestMessage(HttpMethod.Post, url); + options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT)); + options.Headers.TryAddWithoutValidation("SOAPACTION", soapAction); + options.Headers.TryAddWithoutValidation("Pragma", "no-cache"); + options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName); if (!string.IsNullOrEmpty(header)) { - options.RequestHeaders["contentFeatures.dlna.org"] = header; + options.Headers.TryAddWithoutValidation("contentFeatures.dlna.org", header); } - options.RequestContentType = "text/xml"; - options.RequestContent = postData; + options.Content = new StringContent(postData, Encoding.UTF8, MediaTypeNames.Text.Xml); - return _httpClient.Post(options); + return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken); } } } diff --git a/Emby.Dlna/Service/BaseService.cs b/Emby.Dlna/Service/BaseService.cs index 40d069e7cd..a97c4d63a6 100644 --- a/Emby.Dlna/Service/BaseService.cs +++ b/Emby.Dlna/Service/BaseService.cs @@ -1,25 +1,21 @@ #pragma warning disable CS1591 +using System.Net.Http; using Emby.Dlna.Eventing; -using MediaBrowser.Common.Net; using Microsoft.Extensions.Logging; namespace Emby.Dlna.Service { public class BaseService : IDlnaEventManager { - protected BaseService(ILogger logger, IHttpClient httpClient) + protected BaseService(ILogger logger, IHttpClientFactory httpClientFactory) { Logger = logger; - HttpClient = httpClient; - - EventManager = new DlnaEventManager(logger, HttpClient); + EventManager = new DlnaEventManager(logger, httpClientFactory); } protected IDlnaEventManager EventManager { get; } - protected IHttpClient HttpClient { get; } - protected ILogger Logger { get; } public EventSubscriptionResponse CancelEventSubscription(string subscriptionId) From 533b9816683000e3a7e724483ce2a4f9317207b8 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 11:30:05 -0600 Subject: [PATCH 04/26] migrate to IHttpClientFactory in InstallationManager --- .../Updates/InstallationManager.cs | 88 ++++++++----------- 1 file changed, 36 insertions(+), 52 deletions(-) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 4f54c06dd2..f121a34938 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Updates /// private readonly ILogger _logger; private readonly IApplicationPaths _appPaths; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IJsonSerializer _jsonSerializer; private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; @@ -63,7 +63,7 @@ namespace Emby.Server.Implementations.Updates ILogger logger, IApplicationHost appHost, IApplicationPaths appPaths, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, IJsonSerializer jsonSerializer, IServerConfigurationManager config, IFileSystem fileSystem, @@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Updates _logger = logger; _applicationHost = appHost; _appPaths = appPaths; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _jsonSerializer = jsonSerializer; _config = config; _fileSystem = fileSystem; @@ -116,26 +116,18 @@ namespace Emby.Server.Implementations.Updates { try { - using (var response = await _httpClient.SendAsync( - new HttpRequestOptions - { - Url = manifest, - CancellationToken = cancellationToken, - CacheMode = CacheMode.Unconditional, - CacheLength = TimeSpan.FromMinutes(3) - }, - HttpMethod.Get).ConfigureAwait(false)) - using (Stream stream = response.Content) + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(manifest, cancellationToken).ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + + try { - try - { - return await _jsonSerializer.DeserializeFromStreamAsync>(stream).ConfigureAwait(false); - } - catch (SerializationException ex) - { - _logger.LogError(ex, "Failed to deserialize the plugin manifest retrieved from {Manifest}", manifest); - return Array.Empty(); - } + return await _jsonSerializer.DeserializeFromStreamAsync>(stream).ConfigureAwait(false); + } + catch (SerializationException ex) + { + _logger.LogError(ex, "Failed to deserialize the plugin manifest retrieved from {Manifest}", manifest); + return Array.Empty(); } } catch (UriFormatException ex) @@ -360,42 +352,34 @@ namespace Emby.Server.Implementations.Updates // Always override the passed-in target (which is a file) and figure it out again string targetDir = Path.Combine(_appPaths.PluginsPath, package.Name); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(package.SourceUrl, cancellationToken).ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + // CA5351: Do Not Use Broken Cryptographic Algorithms #pragma warning disable CA5351 - using (var res = await _httpClient.SendAsync( - new HttpRequestOptions - { - Url = package.SourceUrl, - CancellationToken = cancellationToken, - // We need it to be buffered for setting the position - BufferContent = true - }, - HttpMethod.Get).ConfigureAwait(false)) - using (var stream = res.Content) - using (var md5 = MD5.Create()) - { - cancellationToken.ThrowIfCancellationRequested(); + using var md5 = MD5.Create(); + cancellationToken.ThrowIfCancellationRequested(); - var hash = Hex.Encode(md5.ComputeHash(stream)); - if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase)) - { - _logger.LogError( - "The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}", - package.Name, - package.Checksum, - hash); - throw new InvalidDataException("The checksum of the received data doesn't match."); - } - - if (Directory.Exists(targetDir)) - { - Directory.Delete(targetDir, true); - } + var hash = Hex.Encode(md5.ComputeHash(stream)); + if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase)) + { + _logger.LogError( + "The checksums didn't match while installing {Package}, expected: {Expected}, got: {Received}", + package.Name, + package.Checksum, + hash); + throw new InvalidDataException("The checksum of the received data doesn't match."); + } - stream.Position = 0; - _zipClient.ExtractAllFromZip(stream, targetDir, true); + if (Directory.Exists(targetDir)) + { + Directory.Delete(targetDir, true); } + stream.Position = 0; + _zipClient.ExtractAllFromZip(stream, targetDir, true); + #pragma warning restore CA5351 } From 6d19adbecfb7ef255de7ec0ece28dd96dc2c6772 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 11:36:29 -0600 Subject: [PATCH 05/26] migrate to IHttpClientFactory in ApplicationHost --- .../ApplicationHost.cs | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index a2d6e2c9e1..9ae010d7c0 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -49,6 +49,7 @@ using Jellyfin.Api.Helpers; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; +using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; @@ -123,7 +124,7 @@ namespace Emby.Server.Implementations private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; private IHttpServer _httpServer; - private IHttpClient _httpClient; + private IHttpClientFactory _httpClientFactory; /// /// Gets a value indicating whether this instance can self restart. @@ -653,7 +654,7 @@ namespace Emby.Server.Implementations _mediaEncoder = Resolve(); _sessionManager = Resolve(); _httpServer = Resolve(); - _httpClient = Resolve(); + _httpClientFactory = Resolve(); ((AuthenticationRepository)Resolve()).Initialize(); @@ -1298,25 +1299,17 @@ namespace Emby.Server.Implementations try { - using (var response = await _httpClient.SendAsync( - new HttpRequestOptions - { - Url = apiUrl, - LogErrorResponseBody = false, - BufferContent = false, - CancellationToken = cancellationToken - }, HttpMethod.Post).ConfigureAwait(false)) - { - using (var reader = new StreamReader(response.Content)) - { - var result = await reader.ReadToEndAsync().ConfigureAwait(false); - var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase); + using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .SendAsync(request, cancellationToken).ConfigureAwait(false); - _validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid); - Logger.LogDebug("Ping test result to {0}. Success: {1}", apiUrl, valid); - return valid; - } - } + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + var result = await System.Text.Json.JsonSerializer.DeserializeAsync(stream, JsonDefaults.GetOptions(), cancellationToken).ConfigureAwait(false); + var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase); + + _validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid); + Logger.LogDebug("Ping test result to {0}. Success: {1}", apiUrl, valid); + return valid; } catch (OperationCanceledException) { From 804b0fc03431842ed3e54dd2739ce4bc7e681c02 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 11:38:47 -0600 Subject: [PATCH 06/26] migrate to IHttpClientFactory in DirectRecorder --- .../LiveTv/EmbyTV/DirectRecorder.cs | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 2e13a3bb37..b43b88abd9 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -16,13 +16,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public class DirectRecorder : IRecorder { private readonly ILogger _logger; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IStreamHelper _streamHelper; - public DirectRecorder(ILogger logger, IHttpClient httpClient, IStreamHelper streamHelper) + public DirectRecorder(ILogger logger, IHttpClientFactory httpClientFactory, IStreamHelper streamHelper) { _logger = logger; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _streamHelper = streamHelper; } @@ -63,36 +63,24 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private async Task RecordFromMediaSource(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { - var httpRequestOptions = new HttpRequestOptions - { - Url = mediaSource.Path, - BufferContent = false, + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(mediaSource.Path, cancellationToken).ConfigureAwait(false); - // Some remote urls will expect a user agent to be supplied - UserAgent = "Emby/3.0", + _logger.LogInformation("Opened recording stream from tuner provider"); - // Shouldn't matter but may cause issues - DecompressionMethod = CompressionMethods.None - }; + Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - using (var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false)) + using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read)) { - _logger.LogInformation("Opened recording stream from tuner provider"); - - Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - onStarted(); + onStarted(); - _logger.LogInformation("Copying recording stream to file {0}", targetFile); + _logger.LogInformation("Copying recording stream to file {0}", targetFile); - // The media source if infinite so we need to handle stopping ourselves - var durationToken = new CancellationTokenSource(duration); - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + // The media source if infinite so we need to handle stopping ourselves + var durationToken = new CancellationTokenSource(duration); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; - await _streamHelper.CopyUntilCancelled(response.Content, output, 81920, cancellationToken).ConfigureAwait(false); - } + await _streamHelper.CopyUntilCancelled(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), output, 81920, cancellationToken).ConfigureAwait(false); } _logger.LogInformation("Recording completed to file {0}", targetFile); From 50a1e3576504b685449a9e320c027f12e958a965 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 11:39:40 -0600 Subject: [PATCH 07/26] migrate to IHttpClientFactory in EmbyTV --- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 09c52d95bb..ace9aa2ef8 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -48,7 +49,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IServerApplicationHost _appHost; private readonly ILogger _logger; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IServerConfigurationManager _config; private readonly IJsonSerializer _jsonSerializer; @@ -81,7 +82,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV IMediaSourceManager mediaSourceManager, ILogger logger, IJsonSerializer jsonSerializer, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, @@ -94,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _appHost = appHost; _logger = logger; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _config = config; _fileSystem = fileSystem; _libraryManager = libraryManager; @@ -1657,7 +1658,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return new EncodedRecorder(_logger, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _config); } - return new DirectRecorder(_logger, _httpClient, _streamHelper); + return new DirectRecorder(_logger, _httpClientFactory, _streamHelper); } private void OnSuccessfulRecording(TimerInfo timer, string path) From 652e688cc1e63a255056dbef1a9617adb03bdb2f Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 11:57:11 -0600 Subject: [PATCH 08/26] migrate to IHttpClientFactory in SchedulesDirect --- .../LiveTv/Listings/SchedulesDirect.cs | 373 +++++++----------- 1 file changed, 134 insertions(+), 239 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index c4d5cc58aa..439e502781 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -8,6 +8,8 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Mime; +using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; @@ -26,7 +28,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { private readonly ILogger _logger; private readonly IJsonSerializer _jsonSerializer; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly SemaphoreSlim _tokenSemaphore = new SemaphoreSlim(1, 1); private readonly IApplicationHost _appHost; @@ -35,12 +37,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings public SchedulesDirect( ILogger logger, IJsonSerializer jsonSerializer, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, IApplicationHost appHost) { _logger = logger; _jsonSerializer = jsonSerializer; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _appHost = appHost; } @@ -102,95 +104,78 @@ namespace Emby.Server.Implementations.LiveTv.Listings var requestString = _jsonSerializer.SerializeToString(requestList); _logger.LogDebug("Request string for schedules is: {RequestString}", requestString); - var httpOptions = new HttpRequestOptions() - { - Url = ApiUrl + "/schedules", - UserAgent = UserAgent, - CancellationToken = cancellationToken, - LogErrorResponseBody = true, - RequestContent = requestString - }; - - httpOptions.RequestHeaders["token"] = token; + using var options = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/schedules"); + options.Content = new StringContent(requestString, Encoding.UTF8, MediaTypeNames.Application.Json); + options.Headers.TryAddWithoutValidation("token", token); + using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false); + await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync>(responseStream).ConfigureAwait(false); + _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId); - using (var response = await Post(httpOptions, true, info).ConfigureAwait(false)) - { - var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync>(response.Content).ConfigureAwait(false); - _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId); - - httpOptions = new HttpRequestOptions() - { - Url = ApiUrl + "/programs", - UserAgent = UserAgent, - CancellationToken = cancellationToken, - LogErrorResponseBody = true - }; + using var programRequestOptions = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/programs"); + programRequestOptions.Headers.TryAddWithoutValidation("token", token); - httpOptions.RequestHeaders["token"] = token; + var programsID = dailySchedules.SelectMany(d => d.programs.Select(s => s.programID)).Distinct(); + programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programsID) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json); - var programsID = dailySchedules.SelectMany(d => d.programs.Select(s => s.programID)).Distinct(); - httpOptions.RequestContent = "[\"" + string.Join("\", \"", programsID) + "\"]"; + using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false); + await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); + var programDetails = await _jsonSerializer.DeserializeFromStreamAsync>(innerResponseStream).ConfigureAwait(false); + var programDict = programDetails.ToDictionary(p => p.programID, y => y); - using (var innerResponse = await Post(httpOptions, true, info).ConfigureAwait(false)) - { - var programDetails = await _jsonSerializer.DeserializeFromStreamAsync>(innerResponse.Content).ConfigureAwait(false); - var programDict = programDetails.ToDictionary(p => p.programID, y => y); + var programIdsWithImages = + programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID) + .ToList(); - var programIdsWithImages = - programDetails.Where(p => p.hasImageArtwork).Select(p => p.programID) - .ToList(); + var images = await GetImageForPrograms(info, programIdsWithImages, cancellationToken).ConfigureAwait(false); - var images = await GetImageForPrograms(info, programIdsWithImages, cancellationToken).ConfigureAwait(false); + var programsInfo = new List(); + foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs)) + { + // _logger.LogDebug("Proccesing Schedule for statio ID " + stationID + + // " which corresponds to channel " + channelNumber + " and program id " + + // schedule.programID + " which says it has images? " + + // programDict[schedule.programID].hasImageArtwork); - var programsInfo = new List(); - foreach (ScheduleDirect.Program schedule in dailySchedules.SelectMany(d => d.programs)) + if (images != null) + { + var imageIndex = images.FindIndex(i => i.programID == schedule.programID.Substring(0, 10)); + if (imageIndex > -1) { - // _logger.LogDebug("Proccesing Schedule for statio ID " + stationID + - // " which corresponds to channel " + channelNumber + " and program id " + - // schedule.programID + " which says it has images? " + - // programDict[schedule.programID].hasImageArtwork); - - if (images != null) - { - var imageIndex = images.FindIndex(i => i.programID == schedule.programID.Substring(0, 10)); - if (imageIndex > -1) - { - var programEntry = programDict[schedule.programID]; - - var allImages = images[imageIndex].data ?? new List(); - var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase)); - var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase)); - - const double DesiredAspect = 2.0 / 3; + var programEntry = programDict[schedule.programID]; - programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, DesiredAspect) ?? - GetProgramImage(ApiUrl, allImages, true, DesiredAspect); + var allImages = images[imageIndex].data ?? new List(); + var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase)); + var imagesWithoutText = allImages.Where(i => string.Equals(i.text, "no", StringComparison.OrdinalIgnoreCase)); - const double WideAspect = 16.0 / 9; + const double DesiredAspect = 2.0 / 3; - programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, WideAspect); + programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, true, DesiredAspect) ?? + GetProgramImage(ApiUrl, allImages, true, DesiredAspect); - // Don't supply the same image twice - if (string.Equals(programEntry.primaryImage, programEntry.thumbImage, StringComparison.Ordinal)) - { - programEntry.thumbImage = null; - } + const double WideAspect = 16.0 / 9; - programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect); + programEntry.thumbImage = GetProgramImage(ApiUrl, imagesWithText, true, WideAspect); - // programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ?? - // GetProgramImage(ApiUrl, data, "Banner-L1", false) ?? - // GetProgramImage(ApiUrl, data, "Banner-LO", false) ?? - // GetProgramImage(ApiUrl, data, "Banner-LOT", false); - } + // Don't supply the same image twice + if (string.Equals(programEntry.primaryImage, programEntry.thumbImage, StringComparison.Ordinal)) + { + programEntry.thumbImage = null; } - programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.programID])); - } + programEntry.backdropImage = GetProgramImage(ApiUrl, imagesWithoutText, true, WideAspect); - return programsInfo; + // programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ?? + // GetProgramImage(ApiUrl, data, "Banner-L1", false) ?? + // GetProgramImage(ApiUrl, data, "Banner-LO", false) ?? + // GetProgramImage(ApiUrl, data, "Banner-LOT", false); + } } + + programsInfo.Add(GetProgram(channelId, schedule, programDict[schedule.programID])); } + + return programsInfo; } private static int GetSizeOrder(ScheduleDirect.ImageData image) @@ -482,22 +467,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings imageIdString = imageIdString.TrimEnd(',') + "]"; - var httpOptions = new HttpRequestOptions() - { - Url = ApiUrl + "/metadata/programs", - UserAgent = UserAgent, - CancellationToken = cancellationToken, - RequestContent = imageIdString, - LogErrorResponseBody = true, - }; + using var message = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/metadata/programs"); + message.Content = new StringContent(imageIdString, Encoding.UTF8, MediaTypeNames.Application.Json); try { - using (var innerResponse2 = await Post(httpOptions, true, info).ConfigureAwait(false)) - { - return await _jsonSerializer.DeserializeFromStreamAsync>( - innerResponse2.Content).ConfigureAwait(false); - } + using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false); + await using var response = await innerResponse2.Content.ReadAsStreamAsync(); + return await _jsonSerializer.DeserializeFromStreamAsync>( + response).ConfigureAwait(false); } catch (Exception ex) { @@ -518,41 +496,33 @@ namespace Emby.Server.Implementations.LiveTv.Listings return lineups; } - var options = new HttpRequestOptions() - { - Url = ApiUrl + "/headends?country=" + country + "&postalcode=" + location, - UserAgent = UserAgent, - CancellationToken = cancellationToken, - LogErrorResponseBody = true - }; - - options.RequestHeaders["token"] = token; + using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/headends?country=" + country + "&postalcode=" + location); + options.Headers.TryAddWithoutValidation("token", token); try { - using (var httpResponse = await Get(options, false, info).ConfigureAwait(false)) - using (Stream responce = httpResponse.Content) - { - var root = await _jsonSerializer.DeserializeFromStreamAsync>(responce).ConfigureAwait(false); + using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false); + await using var response = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); + + var root = await _jsonSerializer.DeserializeFromStreamAsync>(response).ConfigureAwait(false); - if (root != null) + if (root != null) + { + foreach (ScheduleDirect.Headends headend in root) { - foreach (ScheduleDirect.Headends headend in root) + foreach (ScheduleDirect.Lineup lineup in headend.lineups) { - foreach (ScheduleDirect.Lineup lineup in headend.lineups) + lineups.Add(new NameIdPair { - lineups.Add(new NameIdPair - { - Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name, - Id = lineup.uri.Substring(18) - }); - } + Name = string.IsNullOrWhiteSpace(lineup.name) ? lineup.lineup : lineup.name, + Id = lineup.uri.Substring(18) + }); } } - else - { - _logger.LogInformation("No lineups available"); - } + } + else + { + _logger.LogInformation("No lineups available"); } } catch (Exception ex) @@ -633,46 +603,15 @@ namespace Emby.Server.Implementations.LiveTv.Listings } } - private async Task Post(HttpRequestOptions options, - bool enableRetry, - ListingsProviderInfo providerInfo) - { - // Schedules direct requires that the client support compression and will return a 400 response without it - options.DecompressionMethod = CompressionMethods.Deflate; - - try - { - return await _httpClient.Post(options).ConfigureAwait(false); - } - catch (HttpException ex) - { - _tokens.Clear(); - - if (!ex.StatusCode.HasValue || (int)ex.StatusCode.Value >= 500) - { - enableRetry = false; - } - - if (!enableRetry) - { - throw; - } - } - - options.RequestHeaders["token"] = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false); - return await Post(options, false, providerInfo).ConfigureAwait(false); - } - - private async Task Get(HttpRequestOptions options, + private async Task Send( + HttpRequestMessage options, bool enableRetry, - ListingsProviderInfo providerInfo) + ListingsProviderInfo providerInfo, + CancellationToken cancellationToken) { - // Schedules direct requires that the client support compression and will return a 400 response without it - options.DecompressionMethod = CompressionMethods.Deflate; - try { - return await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false); + return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); } catch (HttpException ex) { @@ -689,35 +628,28 @@ namespace Emby.Server.Implementations.LiveTv.Listings } } - options.RequestHeaders["token"] = await GetToken(providerInfo, options.CancellationToken).ConfigureAwait(false); - return await Get(options, false, providerInfo).ConfigureAwait(false); + options.Headers.TryAddWithoutValidation("token", await GetToken(providerInfo, cancellationToken).ConfigureAwait(false)); + return await Send(options, false, providerInfo, cancellationToken).ConfigureAwait(false); } - private async Task GetTokenInternal(string username, string password, + private async Task GetTokenInternal( + string username, + string password, CancellationToken cancellationToken) { - var httpOptions = new HttpRequestOptions() - { - Url = ApiUrl + "/token", - UserAgent = UserAgent, - RequestContent = "{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}", - CancellationToken = cancellationToken, - LogErrorResponseBody = true - }; - // _logger.LogInformation("Obtaining token from Schedules Direct from addres: " + httpOptions.Url + " with body " + - // httpOptions.RequestContent); + using var options = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/token"); + options.Content = new StringContent("{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}", Encoding.UTF8, MediaTypeNames.Application.Json); - using (var response = await Post(httpOptions, false, null).ConfigureAwait(false)) + using var response = await Send(options, false, null, cancellationToken).ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + var root = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); + if (root.message == "OK") { - var root = await _jsonSerializer.DeserializeFromStreamAsync(response.Content).ConfigureAwait(false); - if (root.message == "OK") - { - _logger.LogInformation("Authenticated with Schedules Direct token: " + root.token); - return root.token; - } - - throw new Exception("Could not authenticate with Schedules Direct Error: " + root.message); + _logger.LogInformation("Authenticated with Schedules Direct token: " + root.token); + return root.token; } + + throw new Exception("Could not authenticate with Schedules Direct Error: " + root.message); } private async Task AddLineupToAccount(ListingsProviderInfo info, CancellationToken cancellationToken) @@ -736,20 +668,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings _logger.LogInformation("Adding new LineUp "); - var httpOptions = new HttpRequestOptions() - { - Url = ApiUrl + "/lineups/" + info.ListingsId, - UserAgent = UserAgent, - CancellationToken = cancellationToken, - LogErrorResponseBody = true, - BufferContent = false - }; - - httpOptions.RequestHeaders["token"] = token; - - using (await _httpClient.SendAsync(httpOptions, HttpMethod.Put).ConfigureAwait(false)) - { - } + using var options = new HttpRequestMessage(HttpMethod.Put, ApiUrl + "/lineups/" + info.ListingsId); + options.Headers.TryAddWithoutValidation("token", token); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); } private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) @@ -768,25 +689,17 @@ namespace Emby.Server.Implementations.LiveTv.Listings _logger.LogInformation("Headends on account "); - var options = new HttpRequestOptions() - { - Url = ApiUrl + "/lineups", - UserAgent = UserAgent, - CancellationToken = cancellationToken, - LogErrorResponseBody = true - }; - - options.RequestHeaders["token"] = token; + using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/lineups"); + options.Headers.TryAddWithoutValidation("token", token); try { - using (var httpResponse = await Get(options, false, null).ConfigureAwait(false)) - using (var response = httpResponse.Content) - { - var root = await _jsonSerializer.DeserializeFromStreamAsync(response).ConfigureAwait(false); + using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false); + await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); + using var response = httpResponse.Content; + var root = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); - return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase)); - } + return root.lineups.Any(i => string.Equals(info.ListingsId, i.lineup, StringComparison.OrdinalIgnoreCase)); } catch (HttpException ex) { @@ -851,55 +764,37 @@ namespace Emby.Server.Implementations.LiveTv.Listings throw new Exception("token required"); } - var httpOptions = new HttpRequestOptions() - { - Url = ApiUrl + "/lineups/" + listingsId, - UserAgent = UserAgent, - CancellationToken = cancellationToken, - LogErrorResponseBody = true, - }; - - httpOptions.RequestHeaders["token"] = token; + using var options = new HttpRequestMessage(HttpMethod.Get, ApiUrl + "/lineups/" + listingsId); + options.Headers.TryAddWithoutValidation("token", token); var list = new List(); - using (var httpResponse = await Get(httpOptions, true, info).ConfigureAwait(false)) - using (var response = httpResponse.Content) - { - var root = await _jsonSerializer.DeserializeFromStreamAsync(response).ConfigureAwait(false); - _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count); - _logger.LogInformation("Mapping Stations to Channel"); - - var allStations = root.stations ?? Enumerable.Empty(); + using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false); + await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); + var root = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); + _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count); + _logger.LogInformation("Mapping Stations to Channel"); - foreach (ScheduleDirect.Map map in root.map) - { - var channelNumber = GetChannelNumber(map); + var allStations = root.stations ?? Enumerable.Empty(); - var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase)); - if (station == null) - { - station = new ScheduleDirect.Station - { - stationID = map.stationID - }; - } + foreach (ScheduleDirect.Map map in root.map) + { + var channelNumber = GetChannelNumber(map); - var channelInfo = new ChannelInfo - { - Id = station.stationID, - CallSign = station.callsign, - Number = channelNumber, - Name = string.IsNullOrWhiteSpace(station.name) ? channelNumber : station.name - }; + var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase)); + if (station == null) + { + station = new ScheduleDirect.Station {stationID = map.stationID}; + } - if (station.logo != null) - { - channelInfo.ImageUrl = station.logo.URL; - } + var channelInfo = new ChannelInfo {Id = station.stationID, CallSign = station.callsign, Number = channelNumber, Name = string.IsNullOrWhiteSpace(station.name) ? channelNumber : station.name}; - list.Add(channelInfo); + if (station.logo != null) + { + channelInfo.ImageUrl = station.logo.URL; } + + list.Add(channelInfo); } return list; From 97cc3d54bb81ad8a3942508b231a81f3c743b236 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 12:00:09 -0600 Subject: [PATCH 09/26] migrate to IHttpClientFactory in XmlTvListingsProvider --- .../LiveTv/Listings/XmlTvListingsProvider.cs | 31 +++++-------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index f33d071747..2d6f453bd4 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -25,20 +25,20 @@ namespace Emby.Server.Implementations.LiveTv.Listings public class XmlTvListingsProvider : IListingsProvider { private readonly IServerConfigurationManager _config; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; private readonly IFileSystem _fileSystem; private readonly IZipClient _zipClient; public XmlTvListingsProvider( IServerConfigurationManager config, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, ILogger logger, IFileSystem fileSystem, IZipClient zipClient) { _config = config; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _logger = logger; _fileSystem = fileSystem; _zipClient = zipClient; @@ -78,28 +78,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings Directory.CreateDirectory(Path.GetDirectoryName(cacheFile)); - using (var res = await _httpClient.SendAsync( - new HttpRequestOptions - { - CancellationToken = cancellationToken, - Url = path, - DecompressionMethod = CompressionMethods.Gzip, - }, - HttpMethod.Get).ConfigureAwait(false)) - using (var stream = res.Content) - using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew)) + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew)) { - if (res.ContentHeaders.ContentEncoding.Contains("gzip")) - { - using (var gzStream = new GZipStream(stream, CompressionMode.Decompress)) - { - await gzStream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); - } - } - else - { - await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); - } + await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); } return UnzipIfNeeded(path, cacheFile); From 96fdee38cb58004af832dc19ad39d3837e8c79f1 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 12:03:41 -0600 Subject: [PATCH 10/26] migrate to IHttpClientFactory in HdHomerunHost --- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 91 ++++++++----------- 1 file changed, 40 insertions(+), 51 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 2b5f69d41a..418e27eece 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -31,7 +31,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { public class HdHomerunHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost { - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IServerApplicationHost _appHost; private readonly ISocketFactory _socketFactory; private readonly INetworkManager _networkManager; @@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun IServerConfigurationManager config, ILogger logger, IFileSystem fileSystem, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, @@ -51,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun IMemoryCache memoryCache) : base(config, logger, fileSystem, memoryCache) { - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _appHost = appHost; _socketFactory = socketFactory; _networkManager = networkManager; @@ -78,8 +78,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun BufferContent = false }; - using var response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false); - await using var stream = response.Content; + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, cancellationToken).ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(); var lineup = await JsonSerializer.DeserializeAsync>(stream, cancellationToken: cancellationToken) .ConfigureAwait(false) ?? new List(); @@ -133,14 +133,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun try { - using var response = await _httpClient.SendAsync( - new HttpRequestOptions - { - Url = string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), - CancellationToken = cancellationToken, - BufferContent = false - }, HttpMethod.Get).ConfigureAwait(false); - await using var stream = response.Content; + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), cancellationToken) + .ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var discoverResponse = await JsonSerializer.DeserializeAsync(stream, cancellationToken: cancellationToken) .ConfigureAwait(false); @@ -183,48 +179,41 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); - using (var response = await _httpClient.SendAsync( - new HttpRequestOptions() - { - Url = string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), - CancellationToken = cancellationToken, - BufferContent = false - }, - HttpMethod.Get).ConfigureAwait(false)) - using (var stream = response.Content) - using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) - { - var tuners = new List(); - while (!sr.EndOfStream) + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), cancellationToken) + .ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); + var tuners = new List(); + while (!sr.EndOfStream) + { + string line = StripXML(sr.ReadLine()); + if (line.Contains("Channel", StringComparison.Ordinal)) { - string line = StripXML(sr.ReadLine()); - if (line.Contains("Channel", StringComparison.Ordinal)) + LiveTvTunerStatus status; + var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); + var name = line.Substring(0, index - 1); + var currentChannel = line.Substring(index + 7); + if (currentChannel != "none") { - LiveTvTunerStatus status; - var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); - var name = line.Substring(0, index - 1); - var currentChannel = line.Substring(index + 7); - if (currentChannel != "none") - { - status = LiveTvTunerStatus.LiveTv; - } - else - { - status = LiveTvTunerStatus.Available; - } - - tuners.Add(new LiveTvTunerInfo - { - Name = name, - SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber, - ProgramName = currentChannel, - Status = status - }); + status = LiveTvTunerStatus.LiveTv; + } + else + { + status = LiveTvTunerStatus.Available; } - } - return tuners; + tuners.Add(new LiveTvTunerInfo + { + Name = name, + SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber, + ProgramName = currentChannel, + Status = status + }); + } } + + return tuners; } private static string StripXML(string source) @@ -634,7 +623,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun info, streamId, FileSystem, - _httpClient, + _httpClientFactory, Logger, Config, _appHost, From af9ebef577d7c920f7419eae53f6dbae88eb9569 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 12:06:42 -0600 Subject: [PATCH 11/26] migrate to IHttpClientFactory in SharedHttpStream --- .../LiveTv/TunerHosts/SharedHttpStream.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index bc4dcd8946..4c9722b292 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { public class SharedHttpStream : LiveStream, IDirectStreamProvider { - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IServerApplicationHost _appHost; public SharedHttpStream( @@ -29,14 +29,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts TunerHostInfo tunerHostInfo, string originalStreamId, IFileSystem fileSystem, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, ILogger logger, IConfigurationManager configurationManager, IServerApplicationHost appHost, IStreamHelper streamHelper) : base(mediaSource, tunerHostInfo, fileSystem, logger, configurationManager, streamHelper) { - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _appHost = appHost; OriginalStreamId = originalStreamId; EnableStreamSharing = true; @@ -68,12 +68,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts httpRequestOptions.RequestHeaders[header.Key] = header.Value; } - var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) + .GetAsync(url, CancellationToken.None) + .ConfigureAwait(false); var extension = "ts"; var requiresRemux = false; - var contentType = response.ContentType ?? string.Empty; + var contentType = response.Content.Headers.ContentType.ToString(); if (contentType.IndexOf("matroska", StringComparison.OrdinalIgnoreCase) != -1) { requiresRemux = true; @@ -132,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } } - private Task StartStreaming(HttpResponseInfo response, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) + private Task StartStreaming(HttpResponseMessage response, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) { return Task.Run(async () => { @@ -140,8 +142,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); using (response) - using (var stream = response.Content) - using (var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) + await using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + await using (var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) { await StreamHelper.CopyToAsync( stream, From 5b93b3b15eca21fa88d57ef6ec3adc56a4ad1eeb Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 12:08:37 -0600 Subject: [PATCH 12/26] migrate to IHttpClientFactory in M3uParser --- .../LiveTv/TunerHosts/M3uParser.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 875977219a..f066a749e3 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -19,13 +20,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public class M3uParser { private readonly ILogger _logger; - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IServerApplicationHost _appHost; - public M3uParser(ILogger logger, IHttpClient httpClient, IServerApplicationHost appHost) + public M3uParser(ILogger logger, IHttpClientFactory httpClientFactory, IServerApplicationHost appHost) { _logger = logger; - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _appHost = appHost; } @@ -51,13 +52,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { - return _httpClient.Get(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - // Some data providers will require a user agent - UserAgent = _appHost.ApplicationUserAgent - }); + return _httpClientFactory.CreateClient(NamedClient.Default) + .GetStreamAsync(url); } return Task.FromResult((Stream)File.OpenRead(url)); From 6ae4da709eb9e0bf053eddb8ca978034267c2c84 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 12:08:45 -0600 Subject: [PATCH 13/26] migrate to IHttpClientFactory in M3UTunerHost --- .../LiveTv/TunerHosts/M3UTunerHost.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 8fc29fb4a2..8107bc427b 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Extensions; @@ -26,7 +27,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { public class M3UTunerHost : BaseTunerHost, ITunerHost, IConfigurableTunerHost { - private readonly IHttpClient _httpClient; + private readonly IHttpClientFactory _httpClientFactory; private readonly IServerApplicationHost _appHost; private readonly INetworkManager _networkManager; private readonly IMediaSourceManager _mediaSourceManager; @@ -37,14 +38,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts IMediaSourceManager mediaSourceManager, ILogger logger, IFileSystem fileSystem, - IHttpClient httpClient, + IHttpClientFactory httpClientFactory, IServerApplicationHost appHost, INetworkManager networkManager, IStreamHelper streamHelper, IMemoryCache memoryCache) : base(config, logger, fileSystem, memoryCache) { - _httpClient = httpClient; + _httpClientFactory = httpClientFactory; _appHost = appHost; _networkManager = networkManager; _mediaSourceManager = mediaSourceManager; @@ -64,7 +65,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { var channelIdPrefix = GetFullChannelIdPrefix(info); - return await new M3uParser(Logger, _httpClient, _appHost).Parse(info.Url, channelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false); + return await new M3uParser(Logger, _httpClientFactory, _appHost).Parse(info.Url, channelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false); } public Task> GetTunerInfos(CancellationToken cancellationToken) @@ -116,7 +117,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) { - return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config, _appHost, _streamHelper); + return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper); } } @@ -125,7 +126,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public async Task Validate(TunerHostInfo info) { - using (var stream = await new M3uParser(Logger, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) + using (var stream = await new M3uParser(Logger, _httpClientFactory, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) { } } From f498e1ee59af1413cd4f041227b0296f9ec02a21 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 12:10:49 -0600 Subject: [PATCH 14/26] =?UTF-8?q?remove=20IHttpClient=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApplicationHost.cs | 2 - .../HttpClientManager/HttpClientManager.cs | 335 ------------------ MediaBrowser.Common/Net/IHttpClient.cs | 53 --- 3 files changed, 390 deletions(-) delete mode 100644 Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs delete mode 100644 MediaBrowser.Common/Net/IHttpClient.cs diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 9ae010d7c0..fbf4aef8b8 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -523,8 +523,6 @@ namespace Emby.Server.Implementations ServiceCollection.AddSingleton(_fileSystemManager); ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(_networkManager); ServiceCollection.AddSingleton(); diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs deleted file mode 100644 index 25adc58126..0000000000 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ /dev/null @@ -1,335 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using MediaBrowser.Common; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -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 -{ - /// - /// Class HttpClientManager. - /// - public class HttpClientManager : IHttpClient - { - private readonly ILogger _logger; - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - private readonly IApplicationHost _appHost; - - /// - /// Holds a dictionary of http clients by host. Use GetHttpClient(host) to retrieve or create a client for web requests. - /// DON'T dispose it after use. - /// - /// The HTTP clients. - private readonly ConcurrentDictionary _httpClients = new ConcurrentDictionary(); - - /// - /// Initializes a new instance of the class. - /// - public HttpClientManager( - IApplicationPaths appPaths, - ILogger logger, - IFileSystem fileSystem, - IApplicationHost appHost) - { - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _fileSystem = fileSystem; - _appPaths = appPaths ?? throw new ArgumentNullException(nameof(appPaths)); - _appHost = appHost; - } - - /// - /// Gets the correct http client for the given url. - /// - /// The url. - /// HttpClient. - private HttpClient GetHttpClient(string url) - { - var key = GetHostFromUrl(url); - - if (!_httpClients.TryGetValue(key, out var client)) - { - client = new HttpClient() - { - BaseAddress = new Uri(url) - }; - - _httpClients.TryAdd(key, client); - } - - return client; - } - - private HttpRequestMessage GetRequestMessage(HttpRequestOptions options, HttpMethod method) - { - string url = options.Url; - var uriAddress = new Uri(url); - string userInfo = uriAddress.UserInfo; - if (!string.IsNullOrWhiteSpace(userInfo)) - { - _logger.LogWarning("Found userInfo in url: {0} ... url: {1}", userInfo, url); - url = url.Replace(userInfo + '@', string.Empty, StringComparison.Ordinal); - } - - var request = new HttpRequestMessage(method, url); - - foreach (var header in options.RequestHeaders) - { - request.Headers.TryAddWithoutValidation(header.Key, header.Value); - } - - if (options.EnableDefaultUserAgent - && !request.Headers.TryGetValues(HeaderNames.UserAgent, out _)) - { - request.Headers.Add(HeaderNames.UserAgent, _appHost.ApplicationUserAgent); - } - - switch (options.DecompressionMethod) - { - case CompressionMethods.Deflate | CompressionMethods.Gzip: - request.Headers.Add(HeaderNames.AcceptEncoding, new[] { "gzip", "deflate" }); - break; - case CompressionMethods.Deflate: - request.Headers.Add(HeaderNames.AcceptEncoding, "deflate"); - break; - case CompressionMethods.Gzip: - request.Headers.Add(HeaderNames.AcceptEncoding, "gzip"); - break; - default: - break; - } - - if (options.EnableKeepAlive) - { - request.Headers.Add(HeaderNames.Connection, "Keep-Alive"); - } - - // request.Headers.Add(HeaderNames.CacheControl, "no-cache"); - - /* - if (!string.IsNullOrWhiteSpace(userInfo)) - { - var parts = userInfo.Split(':'); - if (parts.Length == 2) - { - request.Headers.Add(HeaderNames., GetCredential(url, parts[0], parts[1]); - } - } - */ - - return request; - } - - /// - /// Gets the response internal. - /// - /// The options. - /// Task{HttpResponseInfo}. - public Task GetResponse(HttpRequestOptions options) - => SendAsync(options, HttpMethod.Get); - - /// - /// Performs a GET request and returns the resulting stream. - /// - /// The options. - /// Task{Stream}. - public async Task Get(HttpRequestOptions options) - { - var response = await GetResponse(options).ConfigureAwait(false); - return response.Content; - } - - /// - /// send as an asynchronous operation. - /// - /// The options. - /// The HTTP method. - /// Task{HttpResponseInfo}. - public Task SendAsync(HttpRequestOptions options, string httpMethod) - => SendAsync(options, new HttpMethod(httpMethod)); - - /// - /// send as an asynchronous operation. - /// - /// The options. - /// The HTTP method. - /// Task{HttpResponseInfo}. - public async Task SendAsync(HttpRequestOptions options, HttpMethod httpMethod) - { - if (options.CacheMode == CacheMode.None) - { - return await SendAsyncInternal(options, httpMethod).ConfigureAwait(false); - } - - var url = options.Url; - var urlHash = url.ToUpperInvariant().GetMD5().ToString("N", CultureInfo.InvariantCulture); - - var responseCachePath = Path.Combine(_appPaths.CachePath, "httpclient", urlHash); - - var response = GetCachedResponse(responseCachePath, options.CacheLength, url); - if (response != null) - { - return response; - } - - response = await SendAsyncInternal(options, httpMethod).ConfigureAwait(false); - - if (response.StatusCode == HttpStatusCode.OK) - { - await CacheResponse(response, responseCachePath).ConfigureAwait(false); - } - - return response; - } - - private HttpResponseInfo GetCachedResponse(string responseCachePath, TimeSpan cacheLength, string url) - { - if (File.Exists(responseCachePath) - && _fileSystem.GetLastWriteTimeUtc(responseCachePath).Add(cacheLength) > DateTime.UtcNow) - { - var stream = new FileStream(responseCachePath, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, true); - - return new HttpResponseInfo - { - ResponseUrl = url, - Content = stream, - StatusCode = HttpStatusCode.OK, - ContentLength = stream.Length - }; - } - - return null; - } - - private async Task CacheResponse(HttpResponseInfo response, string responseCachePath) - { - Directory.CreateDirectory(Path.GetDirectoryName(responseCachePath)); - - using (var fileStream = new FileStream( - responseCachePath, - FileMode.Create, - FileAccess.Write, - FileShare.None, - IODefaults.FileStreamBufferSize, - true)) - { - await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); - - response.Content.Position = 0; - } - } - - private async Task SendAsyncInternal(HttpRequestOptions options, HttpMethod httpMethod) - { - ValidateParams(options); - - options.CancellationToken.ThrowIfCancellationRequested(); - - var client = GetHttpClient(options.Url); - - var httpWebRequest = GetRequestMessage(options, httpMethod); - - if (!string.IsNullOrEmpty(options.RequestContent) - || httpMethod == HttpMethod.Post) - { - if (options.RequestContent != null) - { - httpWebRequest.Content = new StringContent( - options.RequestContent, - null, - options.RequestContentType); - } - else - { - httpWebRequest.Content = new ByteArrayContent(Array.Empty()); - } - } - - options.CancellationToken.ThrowIfCancellationRequested(); - - var response = await client.SendAsync( - httpWebRequest, - options.BufferContent || options.CacheMode == CacheMode.Unconditional ? HttpCompletionOption.ResponseContentRead : HttpCompletionOption.ResponseHeadersRead, - options.CancellationToken).ConfigureAwait(false); - - await EnsureSuccessStatusCode(response, options).ConfigureAwait(false); - - options.CancellationToken.ThrowIfCancellationRequested(); - - var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - return new HttpResponseInfo(response.Headers, response.Content.Headers) - { - Content = stream, - StatusCode = response.StatusCode, - ContentType = response.Content.Headers.ContentType?.MediaType, - ContentLength = response.Content.Headers.ContentLength, - ResponseUrl = response.Content.Headers.ContentLocation?.ToString() - }; - } - - /// - public Task Post(HttpRequestOptions options) - => SendAsync(options, HttpMethod.Post); - - private void ValidateParams(HttpRequestOptions options) - { - if (string.IsNullOrEmpty(options.Url)) - { - throw new ArgumentNullException(nameof(options)); - } - } - - /// - /// Gets the host from URL. - /// - /// The URL. - /// System.String. - private static string GetHostFromUrl(string url) - { - var index = url.IndexOf("://", StringComparison.OrdinalIgnoreCase); - - if (index != -1) - { - url = url.Substring(index + 3); - var host = url.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); - - if (!string.IsNullOrWhiteSpace(host)) - { - return host; - } - } - - return url; - } - - private async Task EnsureSuccessStatusCode(HttpResponseMessage response, HttpRequestOptions options) - { - if (response.IsSuccessStatusCode) - { - return; - } - - if (options.LogErrorResponseBody) - { - string msg = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - _logger.LogError("HTTP request failed with message: {Message}", msg); - } - - throw new HttpException(response.ReasonPhrase) - { - StatusCode = response.StatusCode - }; - } - } -} diff --git a/MediaBrowser.Common/Net/IHttpClient.cs b/MediaBrowser.Common/Net/IHttpClient.cs deleted file mode 100644 index 534e22eddf..0000000000 --- a/MediaBrowser.Common/Net/IHttpClient.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.IO; -using System.Net.Http; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Net -{ - /// - /// Interface IHttpClient. - /// - public interface IHttpClient - { - /// - /// Gets the response. - /// - /// The options. - /// Task{HttpResponseInfo}. - Task GetResponse(HttpRequestOptions options); - - /// - /// Gets the specified options. - /// - /// The options. - /// Task{Stream}. - Task Get(HttpRequestOptions options); - - /// - /// Warning: Deprecated function, - /// use 'Task{HttpResponseInfo} SendAsync(HttpRequestOptions options, HttpMethod httpMethod);' instead - /// Sends the asynchronous. - /// - /// The options. - /// The HTTP method. - /// Task{HttpResponseInfo}. - [Obsolete("Use 'Task{HttpResponseInfo} SendAsync(HttpRequestOptions options, HttpMethod httpMethod);' instead")] - Task SendAsync(HttpRequestOptions options, string httpMethod); - - /// - /// Sends the asynchronous. - /// - /// The options. - /// The HTTP method. - /// Task{HttpResponseInfo}. - Task SendAsync(HttpRequestOptions options, HttpMethod httpMethod); - - /// - /// Posts the specified options. - /// - /// The options. - /// Task{HttpResponseInfo}. - Task Post(HttpRequestOptions options); - } -} From c02d0ceb57b449d6d547a8c877bf15d584717862 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 12:45:23 -0600 Subject: [PATCH 15/26] Add missing using --- Emby.Dlna/Eventing/DlnaEventManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs index fcc2aaa1e3..0c7591494a 100644 --- a/Emby.Dlna/Eventing/DlnaEventManager.cs +++ b/Emby.Dlna/Eventing/DlnaEventManager.cs @@ -177,7 +177,7 @@ namespace Emby.Dlna.Eventing try { - await _httpClientFactory.CreateClient(NamedClient.Default) + using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .SendAsync(options).ConfigureAwait(false); } catch (OperationCanceledException) From 8d592777c4585058945a9a52d159346384445892 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 31 Aug 2020 12:46:42 -0600 Subject: [PATCH 16/26] change to using declaration --- .../LiveTv/EmbyTV/DirectRecorder.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index b43b88abd9..377292cab8 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -70,18 +70,17 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile)); - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - onStarted(); + await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.Read); - _logger.LogInformation("Copying recording stream to file {0}", targetFile); + onStarted(); - // The media source if infinite so we need to handle stopping ourselves - var durationToken = new CancellationTokenSource(duration); - cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + _logger.LogInformation("Copying recording stream to file {0}", targetFile); - await _streamHelper.CopyUntilCancelled(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), output, 81920, cancellationToken).ConfigureAwait(false); - } + // The media source if infinite so we need to handle stopping ourselves + var durationToken = new CancellationTokenSource(duration); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + + await _streamHelper.CopyUntilCancelled(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), output, 81920, cancellationToken).ConfigureAwait(false); _logger.LogInformation("Recording completed to file {0}", targetFile); } From 4038d15c83da055add3cc78df46969f82ee66d1b Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 1 Sep 2020 07:51:06 -0600 Subject: [PATCH 17/26] Properly migrate all HttpCompletionOption --- Emby.Dlna/Eventing/DlnaEventManager.cs | 2 +- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 6 +++--- Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../LiveTv/EmbyTV/DirectRecorder.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 9 +++++---- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 6 +++--- .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 +- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs index 0c7591494a..7d8da86ef9 100644 --- a/Emby.Dlna/Eventing/DlnaEventManager.cs +++ b/Emby.Dlna/Eventing/DlnaEventManager.cs @@ -178,7 +178,7 @@ namespace Emby.Dlna.Eventing try { using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .SendAsync(options).ConfigureAwait(false); + .SendAsync(options, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); } catch (OperationCanceledException) { diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index c6e9e074f1..65f1aab22e 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -84,7 +84,7 @@ namespace Emby.Dlna.PlayTo options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture)); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .SendAsync(options) + .SendAsync(options, HttpCompletionOption.ResponseHeadersRead) .ConfigureAwait(false); } @@ -93,7 +93,7 @@ namespace Emby.Dlna.PlayTo using var options = new HttpRequestMessage(HttpMethod.Get, url); options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT)); options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); using var reader = new StreamReader(stream, Encoding.UTF8); return XDocument.Parse( @@ -126,7 +126,7 @@ namespace Emby.Dlna.PlayTo options.Content = new StringContent(postData, Encoding.UTF8, MediaTypeNames.Text.Xml); - return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken); + return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken); } } } diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index fbf4aef8b8..0060600790 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1299,7 +1299,7 @@ namespace Emby.Server.Implementations { using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .SendAsync(request, cancellationToken).ConfigureAwait(false); + .SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var result = await System.Text.Json.JsonSerializer.DeserializeAsync(stream, JsonDefaults.GetOptions(), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 377292cab8..a1037948b9 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private async Task RecordFromMediaSource(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(mediaSource.Path, cancellationToken).ConfigureAwait(false); + .GetAsync(mediaSource.Path, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); _logger.LogInformation("Opened recording stream from tuner provider"); diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 439e502781..f426a3336d 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -607,11 +607,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings HttpRequestMessage options, bool enableRetry, ListingsProviderInfo providerInfo, - CancellationToken cancellationToken) + CancellationToken cancellationToken, + HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { try { - return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); + return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, completionOption, cancellationToken).ConfigureAwait(false); } catch (HttpException ex) { @@ -670,7 +671,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var options = new HttpRequestMessage(HttpMethod.Put, ApiUrl + "/lineups/" + info.ListingsId); options.Headers.TryAddWithoutValidation("token", token); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); } private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) @@ -694,7 +695,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { - using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false); + using var httpResponse = await Send(options, false, null, cancellationToken, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); using var response = httpResponse.Content; var root = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 418e27eece..1873d17897 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -78,7 +78,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun BufferContent = false }; - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(); var lineup = await JsonSerializer.DeserializeAsync>(stream, cancellationToken: cancellationToken) .ConfigureAwait(false) ?? new List(); @@ -134,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun try { using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), cancellationToken) + .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var discoverResponse = await JsonSerializer.DeserializeAsync(stream, cancellationToken: cancellationToken) @@ -180,7 +180,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), cancellationToken) + .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 4c9722b292..7a16704a97 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -69,7 +69,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(url, CancellationToken.None) + .GetAsync(url, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None) .ConfigureAwait(false); var extension = "ts"; From e1d0b430d95402c694f1686ba6837d27753d6454 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 1 Sep 2020 07:51:55 -0600 Subject: [PATCH 18/26] Remove HttpRequestOptions --- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 9 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 13 --- MediaBrowser.Common/Net/HttpRequestOptions.cs | 105 ------------------ 3 files changed, 1 insertion(+), 126 deletions(-) delete mode 100644 MediaBrowser.Common/Net/HttpRequestOptions.cs diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 1873d17897..28e30fac8b 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -71,15 +71,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); - var options = new HttpRequestOptions - { - Url = model.LineupURL, - CancellationToken = cancellationToken, - BufferContent = false - }; - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync(); + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var lineup = await JsonSerializer.DeserializeAsync>(stream, cancellationToken: cancellationToken) .ConfigureAwait(false) ?? new List(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 7a16704a97..53c81ecd79 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -55,19 +55,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var typeName = GetType().Name; Logger.LogInformation("Opening " + typeName + " Live stream from {0}", url); - var httpRequestOptions = new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - BufferContent = false, - DecompressionMethod = CompressionMethods.None - }; - - foreach (var header in mediaSource.RequiredHttpHeaders) - { - httpRequestOptions.RequestHeaders[header.Key] = header.Value; - } - using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(url, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None) .ConfigureAwait(false); diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs deleted file mode 100644 index 347fc98332..0000000000 --- a/MediaBrowser.Common/Net/HttpRequestOptions.cs +++ /dev/null @@ -1,105 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.Threading; -using Microsoft.Net.Http.Headers; - -namespace MediaBrowser.Common.Net -{ - /// - /// Class HttpRequestOptions. - /// - public class HttpRequestOptions - { - /// - /// Initializes a new instance of the class. - /// - public HttpRequestOptions() - { - RequestHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); - - CacheMode = CacheMode.None; - DecompressionMethod = CompressionMethods.Deflate; - } - - /// - /// Gets or sets the URL. - /// - /// The URL. - public string Url { get; set; } - - public CompressionMethods DecompressionMethod { get; set; } - - /// - /// Gets or sets the accept header. - /// - /// The accept header. - public string AcceptHeader - { - get => GetHeaderValue(HeaderNames.Accept); - set => RequestHeaders[HeaderNames.Accept] = value; - } - - /// - /// Gets or sets the cancellation token. - /// - /// The cancellation token. - public CancellationToken CancellationToken { get; set; } - - /// - /// Gets or sets the user agent. - /// - /// The user agent. - public string UserAgent - { - get => GetHeaderValue(HeaderNames.UserAgent); - set => RequestHeaders[HeaderNames.UserAgent] = value; - } - - /// - /// Gets or sets the referrer. - /// - /// The referrer. - public string Referer - { - get => GetHeaderValue(HeaderNames.Referer); - set => RequestHeaders[HeaderNames.Referer] = value; - } - - /// - /// Gets or sets the host. - /// - /// The host. - public string Host - { - get => GetHeaderValue(HeaderNames.Host); - set => RequestHeaders[HeaderNames.Host] = value; - } - - public Dictionary RequestHeaders { get; private set; } - - public string RequestContentType { get; set; } - - public string RequestContent { get; set; } - - public bool BufferContent { get; set; } - - public bool LogErrorResponseBody { get; set; } - - public bool EnableKeepAlive { get; set; } - - public CacheMode CacheMode { get; set; } - - public TimeSpan CacheLength { get; set; } - - public bool EnableDefaultUserAgent { get; set; } - - private string GetHeaderValue(string name) - { - RequestHeaders.TryGetValue(name, out var value); - - return value; - } - } -} From 39041019e72709e938c789f495286a3fd1ce24fd Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 1 Sep 2020 07:53:57 -0600 Subject: [PATCH 19/26] Remove CacheMode, CompressionMethods, HttpResponseInfo --- MediaBrowser.Common/Net/CacheMode.cs | 11 --- MediaBrowser.Common/Net/CompressionMethods.cs | 15 ---- MediaBrowser.Common/Net/HttpResponseInfo.cs | 80 ------------------- 3 files changed, 106 deletions(-) delete mode 100644 MediaBrowser.Common/Net/CacheMode.cs delete mode 100644 MediaBrowser.Common/Net/CompressionMethods.cs delete mode 100644 MediaBrowser.Common/Net/HttpResponseInfo.cs diff --git a/MediaBrowser.Common/Net/CacheMode.cs b/MediaBrowser.Common/Net/CacheMode.cs deleted file mode 100644 index 78fa3bf9bb..0000000000 --- a/MediaBrowser.Common/Net/CacheMode.cs +++ /dev/null @@ -1,11 +0,0 @@ -#pragma warning disable CS1591 -#pragma warning disable SA1602 - -namespace MediaBrowser.Common.Net -{ - public enum CacheMode - { - None = 0, - Unconditional = 1 - } -} diff --git a/MediaBrowser.Common/Net/CompressionMethods.cs b/MediaBrowser.Common/Net/CompressionMethods.cs deleted file mode 100644 index 39b72609fe..0000000000 --- a/MediaBrowser.Common/Net/CompressionMethods.cs +++ /dev/null @@ -1,15 +0,0 @@ -#pragma warning disable CS1591 -#pragma warning disable SA1602 - -using System; - -namespace MediaBrowser.Common.Net -{ - [Flags] - public enum CompressionMethods - { - None = 0b00000001, - Deflate = 0b00000010, - Gzip = 0b00000100 - } -} diff --git a/MediaBrowser.Common/Net/HttpResponseInfo.cs b/MediaBrowser.Common/Net/HttpResponseInfo.cs deleted file mode 100644 index d4fee6c78e..0000000000 --- a/MediaBrowser.Common/Net/HttpResponseInfo.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.IO; -using System.Net; -using System.Net.Http.Headers; - -namespace MediaBrowser.Common.Net -{ - /// - /// Class HttpResponseInfo. - /// - public sealed class HttpResponseInfo : IDisposable - { -#pragma warning disable CS1591 - public HttpResponseInfo() - { - } - - public HttpResponseInfo(HttpResponseHeaders headers, HttpContentHeaders contentHeader) - { - Headers = headers; - ContentHeaders = contentHeader; - } - -#pragma warning restore CS1591 - - /// - /// Gets or sets the type of the content. - /// - /// The type of the content. - public string ContentType { get; set; } - - /// - /// Gets or sets the response URL. - /// - /// The response URL. - public string ResponseUrl { get; set; } - - /// - /// Gets or sets the content. - /// - /// The content. - public Stream Content { get; set; } - - /// - /// Gets or sets the status code. - /// - /// The status code. - public HttpStatusCode StatusCode { get; set; } - - /// - /// Gets or sets the temp file path. - /// - /// The temp file path. - public string TempFilePath { get; set; } - - /// - /// Gets or sets the length of the content. - /// - /// The length of the content. - public long? ContentLength { get; set; } - - /// - /// Gets or sets the headers. - /// - /// The headers. - public HttpResponseHeaders Headers { get; set; } - - /// - /// Gets or sets the content headers. - /// - /// The content headers. - public HttpContentHeaders ContentHeaders { get; set; } - - /// - public void Dispose() - { - // backwards compatibility - } - } -} From b111b9e2c93db9bfc51fede80c5ddc14e2ad194e Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 1 Sep 2020 07:58:05 -0600 Subject: [PATCH 20/26] Fix styling --- .../LiveTv/Listings/SchedulesDirect.cs | 10 ++++++++-- .../LiveTv/TunerHosts/SharedHttpStream.cs | 20 +++++++++---------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index f426a3336d..1543badf0a 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -785,10 +785,16 @@ namespace Emby.Server.Implementations.LiveTv.Listings var station = allStations.FirstOrDefault(item => string.Equals(item.stationID, map.stationID, StringComparison.OrdinalIgnoreCase)); if (station == null) { - station = new ScheduleDirect.Station {stationID = map.stationID}; + station = new ScheduleDirect.Station { stationID = map.stationID }; } - var channelInfo = new ChannelInfo {Id = station.stationID, CallSign = station.callsign, Number = channelNumber, Name = string.IsNullOrWhiteSpace(station.name) ? channelNumber : station.name}; + var channelInfo = new ChannelInfo + { + Id = station.stationID, + CallSign = station.callsign, + Number = channelNumber, + Name = string.IsNullOrWhiteSpace(station.name) ? channelNumber : station.name + }; if (station.logo != null) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 53c81ecd79..6c10fca8c6 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -128,17 +128,15 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts try { Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath); - using (response) - await using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - await using (var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - await StreamHelper.CopyToAsync( - stream, - fileStream, - IODefaults.CopyToBufferSize, - () => Resolve(openTaskCompletionSource), - cancellationToken).ConfigureAwait(false); - } + using var message = response; + await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); + await StreamHelper.CopyToAsync( + stream, + fileStream, + IODefaults.CopyToBufferSize, + () => Resolve(openTaskCompletionSource), + cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException ex) { From b398c35068cc610d148660cba387006991a21e40 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 1 Sep 2020 13:16:19 -0600 Subject: [PATCH 21/26] use UserAgent.ParseAdd where possible --- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index 65f1aab22e..8683c89971 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -77,7 +77,7 @@ namespace Emby.Dlna.PlayTo int timeOut = 3600) { using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url); - options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT)); + options.Headers.UserAgent.ParseAdd(USERAGENT); options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture)); options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">"); options.Headers.TryAddWithoutValidation("NT", "upnp:event"); @@ -91,7 +91,7 @@ namespace Emby.Dlna.PlayTo public async Task GetDataAsync(string url, CancellationToken cancellationToken) { using var options = new HttpRequestMessage(HttpMethod.Get, url); - options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT)); + options.Headers.UserAgent.ParseAdd(USERAGENT); options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); @@ -114,7 +114,7 @@ namespace Emby.Dlna.PlayTo } using var options = new HttpRequestMessage(HttpMethod.Post, url); - options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT)); + options.Headers.UserAgent.ParseAdd(USERAGENT); options.Headers.TryAddWithoutValidation("SOAPACTION", soapAction); options.Headers.TryAddWithoutValidation("Pragma", "no-cache"); options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName); From 85844a84b68f7da07695c4e3fa4d187acc559797 Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 3 Sep 2020 06:48:19 -0600 Subject: [PATCH 22/26] Remove ResponseHeadersRead where applicable --- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 1 - Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 9 ++++----- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 6 +++--- .../Plugins/MusicBrainz/AlbumProvider.cs | 1 - 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index 8683c89971..a2f49802ed 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -4,7 +4,6 @@ using System; using System.Globalization; using System.IO; using System.Net.Http; -using System.Net.Http.Headers; using System.Net.Mime; using System.Text; using System.Threading; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0060600790..fbf4aef8b8 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1299,7 +1299,7 @@ namespace Emby.Server.Implementations { using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + .SendAsync(request, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var result = await System.Text.Json.JsonSerializer.DeserializeAsync(stream, JsonDefaults.GetOptions(), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 1543badf0a..5c53d4231d 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -607,12 +607,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings HttpRequestMessage options, bool enableRetry, ListingsProviderInfo providerInfo, - CancellationToken cancellationToken, - HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) + CancellationToken cancellationToken) { try { - return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, completionOption, cancellationToken).ConfigureAwait(false); + return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); } catch (HttpException ex) { @@ -671,7 +670,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var options = new HttpRequestMessage(HttpMethod.Put, ApiUrl + "/lineups/" + info.ListingsId); options.Headers.TryAddWithoutValidation("token", token); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); } private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) @@ -695,7 +694,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { - using var httpResponse = await Send(options, false, null, cancellationToken, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false); await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); using var response = httpResponse.Content; var root = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 28e30fac8b..fec7c4782b 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var lineup = await JsonSerializer.DeserializeAsync>(stream, cancellationToken: cancellationToken) .ConfigureAwait(false) ?? new List(); @@ -127,7 +127,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun try { using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) + .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), cancellationToken) .ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var discoverResponse = await JsonSerializer.DeserializeAsync(stream, cancellationToken: cancellationToken) @@ -173,7 +173,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) + .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), cancellationToken) .ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index 8414c93281..f06face667 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -8,7 +8,6 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Http.Headers; using System.Text; using System.Threading; using System.Threading.Tasks; From d8a0edc511f9a0a01211c11d4ad32bf0fd154de1 Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 3 Sep 2020 07:20:33 -0600 Subject: [PATCH 23/26] Revert "Remove ResponseHeadersRead where applicable" This reverts commit 85844a84b68f7da07695c4e3fa4d187acc559797. --- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 1 + Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 9 +++++---- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 6 +++--- .../Plugins/MusicBrainz/AlbumProvider.cs | 1 + 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index a2f49802ed..8683c89971 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -4,6 +4,7 @@ using System; using System.Globalization; using System.IO; using System.Net.Http; +using System.Net.Http.Headers; using System.Net.Mime; using System.Text; using System.Threading; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index fbf4aef8b8..0060600790 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1299,7 +1299,7 @@ namespace Emby.Server.Implementations { using var request = new HttpRequestMessage(HttpMethod.Post, apiUrl); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .SendAsync(request, cancellationToken).ConfigureAwait(false); + .SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var result = await System.Text.Json.JsonSerializer.DeserializeAsync(stream, JsonDefaults.GetOptions(), cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 5c53d4231d..1543badf0a 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -607,11 +607,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings HttpRequestMessage options, bool enableRetry, ListingsProviderInfo providerInfo, - CancellationToken cancellationToken) + CancellationToken cancellationToken, + HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { try { - return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); + return await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, completionOption, cancellationToken).ConfigureAwait(false); } catch (HttpException ex) { @@ -670,7 +671,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var options = new HttpRequestMessage(HttpMethod.Put, ApiUrl + "/lineups/" + info.ListingsId); options.Headers.TryAddWithoutValidation("token", token); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); } private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) @@ -694,7 +695,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { - using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false); + using var httpResponse = await Send(options, false, null, cancellationToken, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); using var response = httpResponse.Content; var root = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index fec7c4782b..28e30fac8b 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var lineup = await JsonSerializer.DeserializeAsync>(stream, cancellationToken: cancellationToken) .ConfigureAwait(false) ?? new List(); @@ -127,7 +127,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun try { using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), cancellationToken) + .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var discoverResponse = await JsonSerializer.DeserializeAsync(stream, cancellationToken: cancellationToken) @@ -173,7 +173,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), cancellationToken) + .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs index f06face667..8414c93281 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Text; using System.Threading; using System.Threading.Tasks; From 4d4dc0b555a96084d3531157e22574e96766eb3e Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 3 Sep 2020 07:22:32 -0600 Subject: [PATCH 24/26] Remove ResponseHeadersRead in SchedulesDirect --- .../LiveTv/Listings/SchedulesDirect.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 1543badf0a..96cf761d5f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -671,7 +671,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var options = new HttpRequestMessage(HttpMethod.Put, ApiUrl + "/lineups/" + info.ListingsId); options.Headers.TryAddWithoutValidation("token", token); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); } private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) @@ -695,7 +695,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { - using var httpResponse = await Send(options, false, null, cancellationToken, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false); await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false); using var response = httpResponse.Content; var root = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); From ae8ff1ca54fd5a4081c2e63a5ea1505ba0a69657 Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 3 Sep 2020 07:30:34 -0600 Subject: [PATCH 25/26] last time I swear --- Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 96cf761d5f..0f28f19556 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -671,7 +671,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var options = new HttpRequestMessage(HttpMethod.Put, ApiUrl + "/lineups/" + info.ListingsId); options.Headers.TryAddWithoutValidation("token", token); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); } private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) From 23df4991b67576d9150bdf2b3240738968cad9a1 Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 4 Sep 2020 08:24:21 -0600 Subject: [PATCH 26/26] Use proper buffer size --- Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index cdabc07054..44560d1e21 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV await _streamHelper.CopyUntilCancelled( await response.Content.ReadAsStreamAsync().ConfigureAwait(false), output, - 81920, + IODefaults.CopyToBufferSize, cancellationToken).ConfigureAwait(false); _logger.LogInformation("Recording completed to file {0}", targetFile);