Parcourir la source

Remove IHttpClient from Providers

crobibero il y a 4 ans
Parent
commit
1325815182
36 fichiers modifiés avec 483 ajouts et 765 suppressions
  1. 3 3
      Jellyfin.Api/Controllers/ItemLookupController.cs
  2. 2 1
      MediaBrowser.Controller/Providers/IProviderManager.cs
  3. 2 1
      MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs
  4. 1 1
      MediaBrowser.Providers/Manager/ProviderManager.cs
  5. 0 1
      MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
  6. 8 17
      MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs
  7. 10 21
      MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs
  8. 94 119
      MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs
  9. 9 15
      MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
  10. 7 7
      MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs
  11. 7 11
      MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs
  12. 61 69
      MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
  13. 15 30
      MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs
  14. 6 10
      MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs
  15. 6 10
      MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs
  16. 6 10
      MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs
  17. 6 10
      MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs
  18. 6 10
      MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs
  19. 6 11
      MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs
  20. 6 10
      MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs
  21. 16 36
      MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs
  22. 6 10
      MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs
  23. 28 75
      MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
  24. 51 75
      MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs
  25. 2 2
      MediaBrowser.Providers/Plugins/Tmdb/Music/TmdbMusicVideoProvider.cs
  26. 6 10
      MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs
  27. 20 41
      MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
  28. 4 4
      MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs
  29. 4 4
      MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
  30. 12 22
      MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs
  31. 6 10
      MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs
  32. 12 22
      MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
  33. 6 10
      MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
  34. 43 66
      MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs
  35. 6 10
      MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs
  36. 0 1
      MediaBrowser.Providers/Studios/StudiosImageProvider.cs

+ 3 - 3
Jellyfin.Api/Controllers/ItemLookupController.cs

@@ -331,12 +331,12 @@ namespace Jellyfin.Api.Controllers
         /// <returns>Task.</returns>
         private async Task DownloadImage(string providerName, string url, Guid urlHash, string pointerCachePath)
         {
-            var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false);
-            var ext = result.ContentType.Split('/').Last();
+            using var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false);
+            var ext = result.Content.Headers.ContentType.MediaType.Split('/').LastOrDefault();
             var fullCachePath = GetFullCachePath(urlHash + "." + ext);
 
             Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
-            await using (var stream = result.Content)
+            using (var stream = result.Content)
             {
                 await using var fileStream = new FileStream(
                     fullCachePath,

+ 2 - 1
MediaBrowser.Controller/Providers/IProviderManager.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Net.Http;
 using System.Threading;
 using System.Threading.Tasks;
 using Jellyfin.Data.Entities;
@@ -157,7 +158,7 @@ namespace MediaBrowser.Controller.Providers
         /// <param name="url">The URL.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{HttpResponseInfo}.</returns>
-        Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
+        Task<HttpResponseMessage> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
 
         Dictionary<Guid, Guid> GetRefreshQueue();
 

+ 2 - 1
MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs

@@ -1,3 +1,4 @@
+using System.Net.Http;
 using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Common.Net;
@@ -12,6 +13,6 @@ namespace MediaBrowser.Controller.Providers
         /// <param name="url">The URL.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{HttpResponseInfo}.</returns>
-        Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken);
+        Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken);
     }
 }

+ 1 - 1
MediaBrowser.Providers/Manager/ProviderManager.cs

@@ -893,7 +893,7 @@ namespace MediaBrowser.Providers.Manager
         }
 
         /// <inheritdoc/>
-        public Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetSearchImage(string providerName, string url, CancellationToken cancellationToken)
         {
             var provider = _metadataProviders.OfType<IRemoteSearchProvider>().FirstOrDefault(i => string.Equals(i.Name, providerName, StringComparison.OrdinalIgnoreCase));
 

+ 0 - 1
MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs

@@ -8,7 +8,6 @@ using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.IO;
 
 namespace MediaBrowser.Providers.MediaInfo
 {

+ 8 - 17
MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs

@@ -10,7 +10,6 @@ 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;
@@ -26,16 +25,16 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
     {
         private readonly IServerConfigurationManager _config;
         private readonly IFileSystem _fileSystem;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IJsonSerializer _json;
 
         public static AudioDbAlbumProvider Current;
 
-        public AudioDbAlbumProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClient httpClient, IJsonSerializer json)
+        public AudioDbAlbumProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory, IJsonSerializer json)
         {
             _config = config;
             _fileSystem = fileSystem;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _json = json;
 
             Current = this;
@@ -174,18 +173,10 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
 
             Directory.CreateDirectory(Path.GetDirectoryName(path));
 
-            using (var httpResponse = await _httpClient.SendAsync(
-                new HttpRequestOptions
-                {
-                    Url = url,
-                    CancellationToken = cancellationToken
-                },
-                HttpMethod.Get).ConfigureAwait(false))
-            using (var response = httpResponse.Content)
-            using (var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true))
-            {
-                await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
-            }
+            using var response = await _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
+            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);
         }
 
         private static string GetAlbumDataPath(IApplicationPaths appPaths, string musicBrainzReleaseGroupId)
@@ -294,7 +285,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
         }
 
         /// <inheritdoc />
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             throw new NotImplementedException();
         }

+ 10 - 21
MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs

@@ -9,7 +9,6 @@ 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;
@@ -25,7 +24,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
     {
         private readonly IServerConfigurationManager _config;
         private readonly IFileSystem _fileSystem;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IJsonSerializer _json;
 
         public static AudioDbArtistProvider Current;
@@ -33,11 +32,11 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
         private const string ApiKey = "195003";
         public const string BaseUrl = "https://www.theaudiodb.com/api/v1/json/" + ApiKey;
 
-        public AudioDbArtistProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClient httpClient, IJsonSerializer json)
+        public AudioDbArtistProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory, IJsonSerializer json)
         {
             _config = config;
             _fileSystem = fileSystem;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _json = json;
             Current = this;
         }
@@ -155,23 +154,13 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
 
             var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
 
-            using (var httpResponse = await _httpClient.SendAsync(
-                new HttpRequestOptions
-                {
-                    Url = url,
-                    CancellationToken = cancellationToken,
-                    BufferContent = true
-                },
-                HttpMethod.Get).ConfigureAwait(false))
-            using (var response = httpResponse.Content)
-            {
-                Directory.CreateDirectory(Path.GetDirectoryName(path));
+            using var response = await _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
 
-                using (var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true))
-                {
-                    await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
-                }
-            }
+            Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+            await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
+            await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
         }
 
         /// <summary>
@@ -289,7 +278,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
         }
 
         /// <inheritdoc />
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             throw new NotImplementedException();
         }

+ 94 - 119
MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs

@@ -8,12 +8,12 @@ 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;
 using System.Xml;
 using MediaBrowser.Common;
-using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
@@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Music
 
         internal static MusicBrainzAlbumProvider Current;
 
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IApplicationHost _appHost;
         private readonly ILogger<MusicBrainzAlbumProvider> _logger;
 
@@ -51,11 +51,11 @@ namespace MediaBrowser.Providers.Music
         private Stopwatch _stopWatchMusicBrainz = new Stopwatch();
 
         public MusicBrainzAlbumProvider(
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             IApplicationHost appHost,
             ILogger<MusicBrainzAlbumProvider> logger)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _appHost = appHost;
             _logger = logger;
 
@@ -123,11 +123,9 @@ namespace MediaBrowser.Providers.Music
 
             if (!string.IsNullOrWhiteSpace(url))
             {
-                using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-                using (var stream = response.Content)
-                {
-                    return GetResultsFromResponse(stream);
-                }
+                using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+                await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                return GetResultsFromResponse(stream);
             }
 
             return Enumerable.Empty<RemoteSearchResult>();
@@ -282,23 +280,19 @@ namespace MediaBrowser.Providers.Music
                 WebUtility.UrlEncode(albumName),
                 artistId);
 
-            using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-            using (var stream = response.Content)
-            using (var oReader = new StreamReader(stream, Encoding.UTF8))
+            using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            using var oReader = new StreamReader(stream, Encoding.UTF8);
+            var settings = new XmlReaderSettings
             {
-                var settings = new XmlReaderSettings()
-                {
-                    ValidationType = ValidationType.None,
-                    CheckCharacters = false,
-                    IgnoreProcessingInstructions = true,
-                    IgnoreComments = true
-                };
+                ValidationType = ValidationType.None,
+                CheckCharacters = false,
+                IgnoreProcessingInstructions = true,
+                IgnoreComments = true
+            };
 
-                using (var reader = XmlReader.Create(oReader, settings))
-                {
-                    return ReleaseResult.Parse(reader).FirstOrDefault();
-                }
-            }
+            using var reader = XmlReader.Create(oReader, settings);
+            return ReleaseResult.Parse(reader).FirstOrDefault();
         }
 
         private async Task<ReleaseResult> GetReleaseResultByArtistName(string albumName, string artistName, CancellationToken cancellationToken)
@@ -309,23 +303,19 @@ namespace MediaBrowser.Providers.Music
                 WebUtility.UrlEncode(albumName),
                 WebUtility.UrlEncode(artistName));
 
-            using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-            using (var stream = response.Content)
-            using (var oReader = new StreamReader(stream, Encoding.UTF8))
+            using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            using var oReader = new StreamReader(stream, Encoding.UTF8);
+            var settings = new XmlReaderSettings()
             {
-                var settings = new XmlReaderSettings()
-                {
-                    ValidationType = ValidationType.None,
-                    CheckCharacters = false,
-                    IgnoreProcessingInstructions = true,
-                    IgnoreComments = true
-                };
+                ValidationType = ValidationType.None,
+                CheckCharacters = false,
+                IgnoreProcessingInstructions = true,
+                IgnoreComments = true
+            };
 
-                using (var reader = XmlReader.Create(oReader, settings))
-                {
-                    return ReleaseResult.Parse(reader).FirstOrDefault();
-                }
-            }
+            using var reader = XmlReader.Create(oReader, settings);
+            return ReleaseResult.Parse(reader).FirstOrDefault();
         }
 
         private class ReleaseResult
@@ -624,30 +614,21 @@ namespace MediaBrowser.Providers.Music
         {
             var url = "/ws/2/release?release-group=" + releaseGroupId.ToString(CultureInfo.InvariantCulture);
 
-            using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-            using (var stream = response.Content)
-            using (var oReader = new StreamReader(stream, Encoding.UTF8))
+            using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            using var oReader = new StreamReader(stream, Encoding.UTF8);
+            var settings = new XmlReaderSettings
             {
-                var settings = new XmlReaderSettings()
-                {
-                    ValidationType = ValidationType.None,
-                    CheckCharacters = false,
-                    IgnoreProcessingInstructions = true,
-                    IgnoreComments = true
-                };
-
-                using (var reader = XmlReader.Create(oReader, settings))
-                {
-                    var result = ReleaseResult.Parse(reader).FirstOrDefault();
+                ValidationType = ValidationType.None,
+                CheckCharacters = false,
+                IgnoreProcessingInstructions = true,
+                IgnoreComments = true
+            };
 
-                    if (result != null)
-                    {
-                        return result.ReleaseId;
-                    }
-                }
-            }
+            using var reader = XmlReader.Create(oReader, settings);
+            var result = ReleaseResult.Parse(reader).FirstOrDefault();
 
-            return null;
+            return result?.ReleaseId;
         }
 
         /// <summary>
@@ -660,59 +641,57 @@ namespace MediaBrowser.Providers.Music
         {
             var url = "/ws/2/release-group/?query=reid:" + releaseEntryId.ToString(CultureInfo.InvariantCulture);
 
-            using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-            using (var stream = response.Content)
-            using (var oReader = new StreamReader(stream, Encoding.UTF8))
+            using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            using var oReader = new StreamReader(stream, Encoding.UTF8);
+            var settings = new XmlReaderSettings
             {
-                var settings = new XmlReaderSettings()
-                {
-                    ValidationType = ValidationType.None,
-                    CheckCharacters = false,
-                    IgnoreProcessingInstructions = true,
-                    IgnoreComments = true
-                };
+                ValidationType = ValidationType.None,
+                CheckCharacters = false,
+                IgnoreProcessingInstructions = true,
+                IgnoreComments = true
+            };
 
-                using (var reader = XmlReader.Create(oReader, settings))
-                {
-                    reader.MoveToContent();
-                    reader.Read();
+            using (var reader = XmlReader.Create(oReader, settings))
+            {
+                reader.MoveToContent();
+                reader.Read();
 
-                    // Loop through each element
-                    while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+                // Loop through each element
+                while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+                {
+                    if (reader.NodeType == XmlNodeType.Element)
                     {
-                        if (reader.NodeType == XmlNodeType.Element)
+                        switch (reader.Name)
                         {
-                            switch (reader.Name)
+                            case "release-group-list":
                             {
-                                case "release-group-list":
-                                    {
-                                        if (reader.IsEmptyElement)
-                                        {
-                                            reader.Read();
-                                            continue;
-                                        }
+                                if (reader.IsEmptyElement)
+                                {
+                                    reader.Read();
+                                    continue;
+                                }
 
-                                        using (var subReader = reader.ReadSubtree())
-                                        {
-                                            return GetFirstReleaseGroupId(subReader);
-                                        }
-                                    }
+                                using (var subReader = reader.ReadSubtree())
+                                {
+                                    return GetFirstReleaseGroupId(subReader);
+                                }
+                            }
 
-                                default:
-                                    {
-                                        reader.Skip();
-                                        break;
-                                    }
+                            default:
+                            {
+                                reader.Skip();
+                                break;
                             }
                         }
-                        else
-                        {
-                            reader.Read();
-                        }
                     }
-
-                    return null;
+                    else
+                    {
+                        reader.Read();
+                    }
                 }
+
+                return null;
             }
         }
 
@@ -755,23 +734,19 @@ namespace MediaBrowser.Providers.Music
         /// A number of retries shall be made in order to try and satisfy the request before
         /// giving up and returning null.
         /// </summary>
-        internal async Task<HttpResponseInfo> GetMusicBrainzResponse(string url, CancellationToken cancellationToken)
+        internal async Task<HttpResponseMessage> GetMusicBrainzResponse(string url, CancellationToken cancellationToken)
         {
-            var options = new HttpRequestOptions
-            {
-                Url = _musicBrainzBaseUrl.TrimEnd('/') + url,
-                CancellationToken = cancellationToken,
-                // MusicBrainz request a contact email address is supplied, as comment, in user agent field:
-                // https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting#User-Agent
-                UserAgent = string.Format(
-                    CultureInfo.InvariantCulture,
-                    "{0} ( {1} )",
-                    _appHost.ApplicationUserAgent,
-                    _appHost.ApplicationUserAgentAddress),
-                BufferContent = false
-            };
+            using var options = new HttpRequestMessage(HttpMethod.Get, _musicBrainzBaseUrl.TrimEnd('/') + url);
+
+            // MusicBrainz request a contact email address is supplied, as comment, in user agent field:
+            // https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting#User-Agent
+            options.Headers.UserAgent.Add(new ProductInfoHeaderValue(string.Format(
+                CultureInfo.InvariantCulture,
+                "{0} ( {1} )",
+                _appHost.ApplicationUserAgent,
+                _appHost.ApplicationUserAgentAddress)));
 
-            HttpResponseInfo response;
+            HttpResponseMessage response;
             var attempts = 0u;
 
             do
@@ -790,7 +765,7 @@ namespace MediaBrowser.Providers.Music
                 _logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds);
                 _stopWatchMusicBrainz.Restart();
 
-                response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false);
+                response = await _httpClientFactory.CreateClient().SendAsync(options).ConfigureAwait(false);
 
                 // We retry a finite number of times, and only whilst MB is indicating 503 (throttling)
             }
@@ -799,14 +774,14 @@ namespace MediaBrowser.Providers.Music
             // Log error if unable to query MB database due to throttling
             if (attempts == MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable)
             {
-                _logger.LogError("GetMusicBrainzResponse: 503 Service Unavailable (throttled) response received {0} times whilst requesting {1}", attempts, options.Url);
+                _logger.LogError("GetMusicBrainzResponse: 503 Service Unavailable (throttled) response received {0} times whilst requesting {1}", attempts, options.RequestUri);
             }
 
             return response;
         }
 
         /// <inheritdoc />
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             throw new NotImplementedException();
         }

+ 9 - 15
MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs

@@ -6,11 +6,11 @@ using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Net;
+using System.Net.Http;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Xml;
-using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Extensions;
 using MediaBrowser.Controller.Providers;
@@ -37,11 +37,9 @@ namespace MediaBrowser.Providers.Music
             {
                 var url = "/ws/2/artist/?query=arid:{0}" + musicBrainzId.ToString(CultureInfo.InvariantCulture);
 
-                using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-                using (var stream = response.Content)
-                {
-                    return GetResultsFromResponse(stream);
-                }
+                using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+                await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                return GetResultsFromResponse(stream);
             }
             else
             {
@@ -51,7 +49,7 @@ namespace MediaBrowser.Providers.Music
                 var url = string.Format("/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
 
                 using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-                using (var stream = response.Content)
+                await using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                 {
                     var results = GetResultsFromResponse(stream).ToList();
 
@@ -66,13 +64,9 @@ namespace MediaBrowser.Providers.Music
                     // Try again using the search with accent characters url
                     url = string.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
 
-                    using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-                    {
-                        using (var stream = response.Content)
-                        {
-                            return GetResultsFromResponse(stream);
-                        }
-                    }
+                    using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
+                    await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                    return GetResultsFromResponse(stream);
                 }
             }
 
@@ -298,7 +292,7 @@ namespace MediaBrowser.Providers.Music
 
         public string Name => "MusicBrainz";
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             throw new NotImplementedException();
         }

+ 7 - 7
MediaBrowser.Providers/Plugins/Omdb/OmdbEpisodeProvider.cs

@@ -1,10 +1,10 @@
 #pragma warning disable CS1591
 
 using System.Collections.Generic;
+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.TV;
 using MediaBrowser.Controller.Library;
@@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
     public class OmdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IHasOrder
     {
         private readonly IJsonSerializer _jsonSerializer;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly OmdbItemProvider _itemProvider;
         private readonly IFileSystem _fileSystem;
         private readonly IServerConfigurationManager _configurationManager;
@@ -28,17 +28,17 @@ namespace MediaBrowser.Providers.Plugins.Omdb
         public OmdbEpisodeProvider(
             IJsonSerializer jsonSerializer,
             IApplicationHost appHost,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             ILibraryManager libraryManager,
             IFileSystem fileSystem,
             IServerConfigurationManager configurationManager)
         {
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _fileSystem = fileSystem;
             _configurationManager = configurationManager;
             _appHost = appHost;
-            _itemProvider = new OmdbItemProvider(jsonSerializer, _appHost, httpClient, libraryManager, fileSystem, configurationManager);
+            _itemProvider = new OmdbItemProvider(jsonSerializer, _appHost, httpClientFactory, libraryManager, fileSystem, configurationManager);
         }
 
         // After TheTvDb
@@ -69,7 +69,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             {
                 if (info.IndexNumber.HasValue && info.ParentIndexNumber.HasValue)
                 {
-                    result.HasMetadata = await new OmdbProvider(_jsonSerializer, _httpClient, _fileSystem, _appHost, _configurationManager)
+                    result.HasMetadata = await new OmdbProvider(_jsonSerializer, _httpClientFactory, _fileSystem, _appHost, _configurationManager)
                         .FetchEpisodeData(result, info.IndexNumber.Value, info.ParentIndexNumber.Value, info.GetProviderId(MetadataProvider.Imdb), seriesImdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
                 }
             }
@@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             return result;
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             return _itemProvider.GetImageResponse(url, cancellationToken);
         }

+ 7 - 11
MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs

@@ -1,10 +1,10 @@
 #pragma warning disable CS1591
 
 using System.Collections.Generic;
+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;
@@ -19,16 +19,16 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 {
     public class OmdbImageProvider : IRemoteImageProvider, IHasOrder
     {
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IFileSystem _fileSystem;
         private readonly IServerConfigurationManager _configurationManager;
         private readonly IApplicationHost _appHost;
 
-        public OmdbImageProvider(IJsonSerializer jsonSerializer, IApplicationHost appHost, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
+        public OmdbImageProvider(IJsonSerializer jsonSerializer, IApplicationHost appHost, IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
         {
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _fileSystem = fileSystem;
             _configurationManager = configurationManager;
             _appHost = appHost;
@@ -48,7 +48,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 
             var list = new List<RemoteImageInfo>();
 
-            var provider = new OmdbProvider(_jsonSerializer, _httpClient, _fileSystem, _appHost, _configurationManager);
+            var provider = new OmdbProvider(_jsonSerializer, _httpClientFactory, _fileSystem, _appHost, _configurationManager);
 
             if (!string.IsNullOrWhiteSpace(imdbId))
             {
@@ -79,13 +79,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             return list;
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
 
         public string Name => "The Open Movie Database";

+ 61 - 69
MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs

@@ -5,10 +5,10 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Net;
+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;
@@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
         IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<Trailer, TrailerInfo>, IHasOrder
     {
         private readonly IJsonSerializer _jsonSerializer;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILibraryManager _libraryManager;
         private readonly IFileSystem _fileSystem;
         private readonly IServerConfigurationManager _configurationManager;
@@ -35,13 +35,13 @@ namespace MediaBrowser.Providers.Plugins.Omdb
         public OmdbItemProvider(
             IJsonSerializer jsonSerializer,
             IApplicationHost appHost,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             ILibraryManager libraryManager,
             IFileSystem fileSystem,
             IServerConfigurationManager configurationManager)
         {
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _libraryManager = libraryManager;
             _fileSystem = fileSystem;
             _configurationManager = configurationManager;
@@ -129,67 +129,63 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 
             var url = OmdbProvider.GetOmdbUrl(urlQuery, _appHost, cancellationToken);
 
-            using (var response = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
+            using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            var resultList = new List<SearchResult>();
+
+            if (isSearch)
             {
-                using (var stream = response.Content)
+                var searchResultList = await _jsonSerializer.DeserializeFromStreamAsync<SearchResultList>(stream).ConfigureAwait(false);
+                if (searchResultList != null && searchResultList.Search != null)
                 {
-                    var resultList = new List<SearchResult>();
-
-                    if (isSearch)
-                    {
-                        var searchResultList = await _jsonSerializer.DeserializeFromStreamAsync<SearchResultList>(stream).ConfigureAwait(false);
-                        if (searchResultList != null && searchResultList.Search != null)
-                        {
-                            resultList.AddRange(searchResultList.Search);
-                        }
-                    }
-                    else
-                    {
-                        var result = await _jsonSerializer.DeserializeFromStreamAsync<SearchResult>(stream).ConfigureAwait(false);
-                        if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase))
-                        {
-                            resultList.Add(result);
-                        }
-                    }
-
-                    return resultList.Select(result =>
-                    {
-                        var item = new RemoteSearchResult
-                        {
-                            IndexNumber = searchInfo.IndexNumber,
-                            Name = result.Title,
-                            ParentIndexNumber = searchInfo.ParentIndexNumber,
-                            SearchProviderName = Name
-                        };
-
-                        if (episodeSearchInfo != null && episodeSearchInfo.IndexNumberEnd.HasValue)
-                        {
-                            item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value;
-                        }
-
-                        item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
-
-                        if (result.Year.Length > 0
-                            && int.TryParse(result.Year.AsSpan().Slice(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear))
-                        {
-                            item.ProductionYear = parsedYear;
-                        }
-
-                        if (!string.IsNullOrEmpty(result.Released)
-                            && DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var released))
-                        {
-                            item.PremiereDate = released;
-                        }
-
-                        if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase))
-                        {
-                            item.ImageUrl = result.Poster;
-                        }
-
-                        return item;
-                    });
+                    resultList.AddRange(searchResultList.Search);
                 }
             }
+            else
+            {
+                var result = await _jsonSerializer.DeserializeFromStreamAsync<SearchResult>(stream).ConfigureAwait(false);
+                if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase))
+                {
+                    resultList.Add(result);
+                }
+            }
+
+            return resultList.Select(result =>
+            {
+                var item = new RemoteSearchResult
+                {
+                    IndexNumber = searchInfo.IndexNumber,
+                    Name = result.Title,
+                    ParentIndexNumber = searchInfo.ParentIndexNumber,
+                    SearchProviderName = Name
+                };
+
+                if (episodeSearchInfo != null && episodeSearchInfo.IndexNumberEnd.HasValue)
+                {
+                    item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value;
+                }
+
+                item.SetProviderId(MetadataProvider.Imdb, result.imdbID);
+
+                if (result.Year.Length > 0
+                    && int.TryParse(result.Year.AsSpan().Slice(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear))
+                {
+                    item.ProductionYear = parsedYear;
+                }
+
+                if (!string.IsNullOrEmpty(result.Released)
+                    && DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var released))
+                {
+                    item.PremiereDate = released;
+                }
+
+                if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase))
+                {
+                    item.ImageUrl = result.Poster;
+                }
+
+                return item;
+            });
         }
 
         public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
@@ -224,7 +220,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 result.Item.SetProviderId(MetadataProvider.Imdb, imdbId);
                 result.HasMetadata = true;
 
-                await new OmdbProvider(_jsonSerializer, _httpClient, _fileSystem, _appHost, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
+                await new OmdbProvider(_jsonSerializer, _httpClientFactory, _fileSystem, _appHost, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
             }
 
             return result;
@@ -256,7 +252,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                 result.Item.SetProviderId(MetadataProvider.Imdb, imdbId);
                 result.HasMetadata = true;
 
-                await new OmdbProvider(_jsonSerializer, _httpClient, _fileSystem, _appHost, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
+                await new OmdbProvider(_jsonSerializer, _httpClientFactory, _fileSystem, _appHost, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
             }
 
             return result;
@@ -276,13 +272,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             return first == null ? null : first.GetProviderId(MetadataProvider.Imdb);
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
 
         class SearchResult

+ 15 - 30
MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs

@@ -10,7 +10,6 @@ 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;
@@ -25,14 +24,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IFileSystem _fileSystem;
         private readonly IServerConfigurationManager _configurationManager;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly CultureInfo _usCulture = new CultureInfo("en-US");
         private readonly IApplicationHost _appHost;
 
-        public OmdbProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem, IApplicationHost appHost, IServerConfigurationManager configurationManager)
+        public OmdbProvider(IJsonSerializer jsonSerializer, IHttpClientFactory httpClientFactory, IFileSystem fileSystem, IApplicationHost appHost, IServerConfigurationManager configurationManager)
         {
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _fileSystem = fileSystem;
             _configurationManager = configurationManager;
             _appHost = appHost;
@@ -293,15 +292,11 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 
             var url = GetOmdbUrl(string.Format("i={0}&plot=short&tomatoes=true&r=json", imdbParam), _appHost, cancellationToken);
 
-            using (var response = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
-            {
-                using (var stream = response.Content)
-                {
-                    var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false);
-                    Directory.CreateDirectory(Path.GetDirectoryName(path));
-                    _jsonSerializer.SerializeToFile(rootObject, path);
-                }
-            }
+            using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false);
+            Directory.CreateDirectory(Path.GetDirectoryName(path));
+            _jsonSerializer.SerializeToFile(rootObject, path);
 
             return path;
         }
@@ -330,28 +325,18 @@ namespace MediaBrowser.Providers.Plugins.Omdb
 
             var url = GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), _appHost, cancellationToken);
 
-            using (var response = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
-            {
-                using (var stream = response.Content)
-                {
-                    var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false);
-                    Directory.CreateDirectory(Path.GetDirectoryName(path));
-                    _jsonSerializer.SerializeToFile(rootObject, path);
-                }
-            }
+            using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false);
+            Directory.CreateDirectory(Path.GetDirectoryName(path));
+            _jsonSerializer.SerializeToFile(rootObject, path);
 
             return path;
         }
 
-        public static Task<HttpResponseInfo> GetOmdbResponse(IHttpClient httpClient, string url, CancellationToken cancellationToken)
+        public static Task<HttpResponseMessage> GetOmdbResponse(HttpClient httpClient, string url, CancellationToken cancellationToken)
         {
-            return httpClient.SendAsync(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                BufferContent = true,
-                EnableDefaultUserAgent = true
-            }, HttpMethod.Get);
+            return httpClient.GetAsync(url, cancellationToken);
         }
 
         internal string GetDataFilePath(string imdbId)

+ 6 - 10
MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs

@@ -2,9 +2,9 @@
 
 using System;
 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;
@@ -18,13 +18,13 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
 {
     public class TvdbEpisodeImageProvider : IRemoteImageProvider
     {
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILogger<TvdbEpisodeImageProvider> _logger;
         private readonly TvdbClientManager _tvdbClientManager;
 
-        public TvdbEpisodeImageProvider(IHttpClient httpClient, ILogger<TvdbEpisodeImageProvider> logger, TvdbClientManager tvdbClientManager)
+        public TvdbEpisodeImageProvider(IHttpClientFactory httpClientFactory, ILogger<TvdbEpisodeImageProvider> logger, TvdbClientManager tvdbClientManager)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
             _tvdbClientManager = tvdbClientManager;
         }
@@ -113,13 +113,9 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
 
         public int Order => 0;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 6 - 10
MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs

@@ -2,9 +2,9 @@
 
 using System;
 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;
@@ -21,13 +21,13 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
     /// </summary>
     public class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IHasOrder
     {
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILogger<TvdbEpisodeProvider> _logger;
         private readonly TvdbClientManager _tvdbClientManager;
 
-        public TvdbEpisodeProvider(IHttpClient httpClient, ILogger<TvdbEpisodeProvider> logger, TvdbClientManager tvdbClientManager)
+        public TvdbEpisodeProvider(IHttpClientFactory httpClientFactory, ILogger<TvdbEpisodeProvider> logger, TvdbClientManager tvdbClientManager)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
             _tvdbClientManager = tvdbClientManager;
         }
@@ -242,13 +242,9 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
             return result;
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
 
         public int Order => 0;

+ 6 - 10
MediaBrowser.Providers/Plugins/TheTvdb/TvdbPersonImageProvider.cs

@@ -3,9 +3,9 @@
 using System;
 using System.Collections.Generic;
 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;
@@ -20,15 +20,15 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
 {
     public class TvdbPersonImageProvider : IRemoteImageProvider, IHasOrder
     {
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILogger<TvdbPersonImageProvider> _logger;
         private readonly ILibraryManager _libraryManager;
         private readonly TvdbClientManager _tvdbClientManager;
 
-        public TvdbPersonImageProvider(ILibraryManager libraryManager, IHttpClient httpClient, ILogger<TvdbPersonImageProvider> logger, TvdbClientManager tvdbClientManager)
+        public TvdbPersonImageProvider(ILibraryManager libraryManager, IHttpClientFactory httpClientFactory, ILogger<TvdbPersonImageProvider> logger, TvdbClientManager tvdbClientManager)
         {
             _libraryManager = libraryManager;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
             _tvdbClientManager = tvdbClientManager;
         }
@@ -104,13 +104,9 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
         }
 
         /// <inheritdoc />
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 6 - 10
MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeasonImageProvider.cs

@@ -3,9 +3,9 @@
 using System;
 using System.Collections.Generic;
 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;
@@ -20,13 +20,13 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
 {
     public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder
     {
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILogger<TvdbSeasonImageProvider> _logger;
         private readonly TvdbClientManager _tvdbClientManager;
 
-        public TvdbSeasonImageProvider(IHttpClient httpClient, ILogger<TvdbSeasonImageProvider> logger, TvdbClientManager tvdbClientManager)
+        public TvdbSeasonImageProvider(IHttpClientFactory httpClientFactory, ILogger<TvdbSeasonImageProvider> logger, TvdbClientManager tvdbClientManager)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
             _tvdbClientManager = tvdbClientManager;
         }
@@ -146,13 +146,9 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
 
         public int Order => 0;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 6 - 10
MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesImageProvider.cs

@@ -3,9 +3,9 @@
 using System;
 using System.Collections.Generic;
 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;
@@ -20,13 +20,13 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
 {
     public class TvdbSeriesImageProvider : IRemoteImageProvider, IHasOrder
     {
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILogger<TvdbSeriesImageProvider> _logger;
         private readonly TvdbClientManager _tvdbClientManager;
 
-        public TvdbSeriesImageProvider(IHttpClient httpClient, ILogger<TvdbSeriesImageProvider> logger, TvdbClientManager tvdbClientManager)
+        public TvdbSeriesImageProvider(IHttpClientFactory httpClientFactory, ILogger<TvdbSeriesImageProvider> logger, TvdbClientManager tvdbClientManager)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
             _tvdbClientManager = tvdbClientManager;
         }
@@ -144,13 +144,9 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
 
         public int Order => 0;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 6 - 11
MediaBrowser.Providers/Plugins/TheTvdb/TvdbSeriesProvider.cs

@@ -3,11 +3,11 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Net.Http;
 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;
@@ -25,15 +25,15 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
     {
         internal static TvdbSeriesProvider Current { get; private set; }
 
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILogger<TvdbSeriesProvider> _logger;
         private readonly ILibraryManager _libraryManager;
         private readonly ILocalizationManager _localizationManager;
         private readonly TvdbClientManager _tvdbClientManager;
 
-        public TvdbSeriesProvider(IHttpClient httpClient, ILogger<TvdbSeriesProvider> logger, ILibraryManager libraryManager, ILocalizationManager localizationManager, TvdbClientManager tvdbClientManager)
+        public TvdbSeriesProvider(IHttpClientFactory httpClientFactory, ILogger<TvdbSeriesProvider> logger, ILibraryManager libraryManager, ILocalizationManager localizationManager, TvdbClientManager tvdbClientManager)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
             _libraryManager = libraryManager;
             _localizationManager = localizationManager;
@@ -408,14 +408,9 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
 
         public int Order => 0;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url,
-                BufferContent = false
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 6 - 10
MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetImageProvider.cs

@@ -3,9 +3,9 @@
 using System;
 using System.Collections.Generic;
 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;
@@ -20,11 +20,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
 {
     public class TmdbBoxSetImageProvider : IRemoteImageProvider, IHasOrder
     {
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
 
-        public TmdbBoxSetImageProvider(IHttpClient httpClient)
+        public TmdbBoxSetImageProvider(IHttpClientFactory httpClientFactory)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
         }
 
         public string Name => ProviderName;
@@ -153,13 +153,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
 
         public int Order => 0;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 16 - 36
MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs

@@ -5,10 +5,11 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
+using System.Net.Http;
+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;
@@ -36,7 +37,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
         private readonly IServerConfigurationManager _config;
         private readonly IFileSystem _fileSystem;
         private readonly ILocalizationManager _localization;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILibraryManager _libraryManager;
 
         public TmdbBoxSetProvider(
@@ -45,7 +46,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
             IServerConfigurationManager config,
             IFileSystem fileSystem,
             ILocalizationManager localization,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             ILibraryManager libraryManager)
         {
             _logger = logger;
@@ -53,7 +54,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
             _config = config;
             _fileSystem = fileSystem;
             _localization = localization;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _libraryManager = libraryManager;
             Current = this;
         }
@@ -187,20 +188,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            CollectionResult mainResult;
-
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
-            }).ConfigureAwait(false))
-            {
-                using (var json = response.Content)
-                {
-                    mainResult = await _json.DeserializeFromStreamAsync<CollectionResult>(json).ConfigureAwait(false);
-                }
-            }
+            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var mainResponse = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage);
+            await using var stream = await mainResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            var mainResult = await _json.DeserializeFromStreamAsync<CollectionResult>(stream).ConfigureAwait(false);
 
             cancellationToken.ThrowIfCancellationRequested();
 
@@ -216,18 +208,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
                         url += "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language);
                     }
 
-                    using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-                    {
-                        Url = url,
-                        CancellationToken = cancellationToken,
-                        AcceptHeader = TmdbUtils.AcceptHeader
-                    }).ConfigureAwait(false))
-                    {
-                        using (var json = response.Content)
-                        {
-                            mainResult = await _json.DeserializeFromStreamAsync<CollectionResult>(json).ConfigureAwait(false);
-                        }
-                    }
+                    using var langRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+                    langRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+                    await using var langStream = await mainResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                    mainResult = await _json.DeserializeFromStreamAsync<CollectionResult>(langStream).ConfigureAwait(false);
                 }
             }
 
@@ -277,13 +261,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
             return dataPath;
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 6 - 10
MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs

@@ -4,9 +4,9 @@ using System;
 using System.Collections.Generic;
 using System.Globalization;
 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;
@@ -23,13 +23,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
     public class TmdbImageProvider : IRemoteImageProvider, IHasOrder
     {
         private readonly IJsonSerializer _jsonSerializer;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IFileSystem _fileSystem;
 
-        public TmdbImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
+        public TmdbImageProvider(IJsonSerializer jsonSerializer, IHttpClientFactory httpClientFactory, IFileSystem fileSystem)
         {
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _fileSystem = fileSystem;
         }
 
@@ -202,13 +202,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
 
         public int Order => 0;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 28 - 75
MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs

@@ -6,11 +6,11 @@ using System.Globalization;
 using System.IO;
 using System.Net;
 using System.Net.Http;
+using System.Net.Http.Headers;
 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;
@@ -18,7 +18,6 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Providers;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Providers.Plugins.Tmdb.Models.Movies;
@@ -34,7 +33,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
         internal static TmdbMovieProvider Current { get; private set; }
 
         private readonly IJsonSerializer _jsonSerializer;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IFileSystem _fileSystem;
         private readonly IServerConfigurationManager _configurationManager;
         private readonly ILogger<TmdbMovieProvider> _logger;
@@ -45,7 +44,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
 
         public TmdbMovieProvider(
             IJsonSerializer jsonSerializer,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             IFileSystem fileSystem,
             IServerConfigurationManager configurationManager,
             ILogger<TmdbMovieProvider> logger,
@@ -53,7 +52,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
             IApplicationHost appHost)
         {
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _fileSystem = fileSystem;
             _configurationManager = configurationManager;
             _logger = logger;
@@ -146,20 +145,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
                 return _tmdbSettings;
             }
 
-            using (HttpResponseInfo response = await GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = string.Format(CultureInfo.InvariantCulture, TmdbConfigUrl, TmdbUtils.ApiKey),
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
-            }).ConfigureAwait(false))
-            {
-                using (Stream json = response.Content)
-                {
-                    _tmdbSettings = await _jsonSerializer.DeserializeFromStreamAsync<TmdbSettingsResult>(json).ConfigureAwait(false);
-
-                    return _tmdbSettings;
-                }
-            }
+            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, string.Format(CultureInfo.InvariantCulture, TmdbConfigUrl, TmdbUtils.ApiKey));
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var response = await GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            _tmdbSettings = await _jsonSerializer.DeserializeFromStreamAsync<TmdbSettingsResult>(stream).ConfigureAwait(false);
+            return _tmdbSettings;
         }
 
         private const string TmdbConfigUrl = TmdbUtils.BaseTmdbApiUrl + "3/configuration?api_key={0}";
@@ -331,41 +322,18 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
                 url += "&include_image_language=" + GetImageLanguagesParam(language);
             }
 
-            MovieResult mainResult;
-
             cancellationToken.ThrowIfCancellationRequested();
 
-            // Cache if not using a tmdbId because we won't have the tmdb cache directory structure. So use the lower level cache.
-            var cacheMode = isTmdbId ? CacheMode.None : CacheMode.Unconditional;
-            var cacheLength = TimeSpan.FromDays(3);
-
-            try
+            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var mainResponse = await GetMovieDbResponse(requestMessage);
+            if (mainResponse.StatusCode == HttpStatusCode.NotFound)
             {
-                using (var response = await GetMovieDbResponse(new HttpRequestOptions
-                {
-                    Url = url,
-                    CancellationToken = cancellationToken,
-                    AcceptHeader = TmdbUtils.AcceptHeader,
-                    CacheMode = cacheMode,
-                    CacheLength = cacheLength
-                }).ConfigureAwait(false))
-                {
-                    using (var json = response.Content)
-                    {
-                        mainResult = await _jsonSerializer.DeserializeFromStreamAsync<MovieResult>(json).ConfigureAwait(false);
-                    }
-                }
+                return null;
             }
-            catch (HttpException ex)
-            {
-                // Return null so that callers know there is no metadata for this id
-                if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
-                {
-                    return null;
-                }
 
-                throw;
-            }
+            await using var stream = await mainResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            var mainResult = await _jsonSerializer.DeserializeFromStreamAsync<MovieResult>(stream).ConfigureAwait(false);
 
             cancellationToken.ThrowIfCancellationRequested();
 
@@ -385,22 +353,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
                     url += "&include_image_language=" + GetImageLanguagesParam(language);
                 }
 
-                using (var response = await GetMovieDbResponse(new HttpRequestOptions
-                {
-                    Url = url,
-                    CancellationToken = cancellationToken,
-                    AcceptHeader = TmdbUtils.AcceptHeader,
-                    CacheMode = cacheMode,
-                    CacheLength = cacheLength
-                }).ConfigureAwait(false))
-                {
-                    using (var json = response.Content)
-                    {
-                        var englishResult = await _jsonSerializer.DeserializeFromStreamAsync<MovieResult>(json).ConfigureAwait(false);
+                using var langRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+                langRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+                using var langResponse = await GetMovieDbResponse(langRequestMessage);
 
-                        mainResult.Overview = englishResult.Overview;
-                    }
-                }
+                await using var langStream = await langResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                var langResult = await _jsonSerializer.DeserializeFromStreamAsync<MovieResult>(stream).ConfigureAwait(false);
+                mainResult.Overview = langResult.Overview;
             }
 
             return mainResult;
@@ -409,25 +368,19 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
         /// <summary>
         /// Gets the movie db response.
         /// </summary>
-        internal async Task<HttpResponseInfo> GetMovieDbResponse(HttpRequestOptions options)
+        internal async Task<HttpResponseMessage> GetMovieDbResponse(HttpRequestMessage message)
         {
-            options.BufferContent = true;
-            options.UserAgent = _appHost.ApplicationUserAgent;
-
-            return await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false);
+            message.Headers.UserAgent.Add(new ProductInfoHeaderValue(_appHost.ApplicationUserAgent));
+            return await _httpClientFactory.CreateClient().SendAsync(message);
         }
 
         /// <inheritdoc />
         public int Order => 1;
 
         /// <inheritdoc />
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 51 - 75
MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs

@@ -5,10 +5,11 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
 using System.Text.RegularExpressions;
 using System.Threading;
 using System.Threading.Tasks;
-using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Entities;
@@ -168,47 +169,34 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
 
             var url3 = string.Format(_searchURL, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, type);
 
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url3,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
+            var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            var searchResults = await _json.DeserializeFromStreamAsync<TmdbSearchResult<MovieResult>>(stream).ConfigureAwait(false);
 
-            }).ConfigureAwait(false))
-            {
-                using (var json = response.Content)
-                {
-                    var searchResults = await _json.DeserializeFromStreamAsync<TmdbSearchResult<MovieResult>>(json).ConfigureAwait(false);
+            var results = searchResults.Results ?? new List<MovieResult>();
 
-                    var results = searchResults.Results ?? new List<MovieResult>();
+            return results
+                .Select(i =>
+                {
+                    var remoteResult = new RemoteSearchResult {SearchProviderName = TmdbMovieProvider.Current.Name, Name = i.Title ?? i.Name ?? i.Original_Title, ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path};
 
-                    return results
-                        .Select(i =>
+                    if (!string.IsNullOrWhiteSpace(i.Release_Date))
+                    {
+                        // These dates are always in this exact format
+                        if (DateTime.TryParseExact(i.Release_Date, "yyyy-MM-dd", _usCulture, DateTimeStyles.None, out var r))
                         {
-                            var remoteResult = new RemoteSearchResult
-                            {
-                                SearchProviderName = TmdbMovieProvider.Current.Name,
-                                Name = i.Title ?? i.Name ?? i.Original_Title,
-                                ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path
-                            };
-
-                            if (!string.IsNullOrWhiteSpace(i.Release_Date))
-                            {
-                                // These dates are always in this exact format
-                                if (DateTime.TryParseExact(i.Release_Date, "yyyy-MM-dd", _usCulture, DateTimeStyles.None, out var r))
-                                {
-                                    remoteResult.PremiereDate = r.ToUniversalTime();
-                                    remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
-                                }
-                            }
-
-                            remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture));
-
-                            return remoteResult;
-                        })
-                        .ToList();
-                }
-            }
+                            remoteResult.PremiereDate = r.ToUniversalTime();
+                            remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
+                        }
+                    }
+
+                    remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture));
+
+                    return remoteResult;
+                })
+                .ToList();
         }
 
         private async Task<List<RemoteSearchResult>> GetSearchResultsTv(string name, int? year, string language, string baseImageUrl, CancellationToken cancellationToken)
@@ -220,46 +208,34 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
 
             var url3 = string.Format(_searchURL, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, "tv");
 
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url3,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
-            }).ConfigureAwait(false))
-            {
-                using (var json = response.Content)
-                {
-                    var searchResults = await _json.DeserializeFromStreamAsync<TmdbSearchResult<TvResult>>(json).ConfigureAwait(false);
+            var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            var searchResults = await _json.DeserializeFromStreamAsync<TmdbSearchResult<TvResult>>(stream).ConfigureAwait(false);
 
-                    var results = searchResults.Results ?? new List<TvResult>();
+            var results = searchResults.Results ?? new List<TvResult>();
 
-                    return results
-                        .Select(i =>
+            return results
+                .Select(i =>
+                {
+                    var remoteResult = new RemoteSearchResult {SearchProviderName = TmdbMovieProvider.Current.Name, Name = i.Name ?? i.Original_Name, ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path};
+
+                    if (!string.IsNullOrWhiteSpace(i.First_Air_Date))
+                    {
+                        // These dates are always in this exact format
+                        if (DateTime.TryParseExact(i.First_Air_Date, "yyyy-MM-dd", _usCulture, DateTimeStyles.None, out var r))
                         {
-                            var remoteResult = new RemoteSearchResult
-                            {
-                                SearchProviderName = TmdbMovieProvider.Current.Name,
-                                Name = i.Name ?? i.Original_Name,
-                                ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path
-                            };
-
-                            if (!string.IsNullOrWhiteSpace(i.First_Air_Date))
-                            {
-                                // These dates are always in this exact format
-                                if (DateTime.TryParseExact(i.First_Air_Date, "yyyy-MM-dd", _usCulture, DateTimeStyles.None, out var r))
-                                {
-                                    remoteResult.PremiereDate = r.ToUniversalTime();
-                                    remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
-                                }
-                            }
-
-                            remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture));
-
-                            return remoteResult;
-                        })
-                        .ToList();
-                }
-            }
+                            remoteResult.PremiereDate = r.ToUniversalTime();
+                            remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
+                        }
+                    }
+
+                    remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture));
+
+                    return remoteResult;
+                })
+                .ToList();
         }
     }
 }

+ 2 - 2
MediaBrowser.Providers/Plugins/Tmdb/Music/TmdbMusicVideoProvider.cs

@@ -2,9 +2,9 @@
 
 using System;
 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;
@@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Music
 
         public string Name => TmdbMovieProvider.Current.Name;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             throw new NotImplementedException();
         }

+ 6 - 10
MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs

@@ -3,9 +3,9 @@
 using System;
 using System.Collections.Generic;
 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;
@@ -22,13 +22,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
     {
         private readonly IServerConfigurationManager _config;
         private readonly IJsonSerializer _jsonSerializer;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
 
-        public TmdbPersonImageProvider(IServerConfigurationManager config, IJsonSerializer jsonSerializer, IHttpClient httpClient)
+        public TmdbPersonImageProvider(IServerConfigurationManager config, IJsonSerializer jsonSerializer, IHttpClientFactory httpClientFactory)
         {
             _config = config;
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
         }
 
         public string Name => ProviderName;
@@ -127,13 +127,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
 
         public int Order => 0;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 20 - 41
MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs

@@ -6,11 +6,12 @@ using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
 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;
@@ -36,20 +37,20 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IFileSystem _fileSystem;
         private readonly IServerConfigurationManager _configurationManager;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILogger<TmdbPersonProvider> _logger;
 
         public TmdbPersonProvider(
             IFileSystem fileSystem,
             IServerConfigurationManager configurationManager,
             IJsonSerializer jsonSerializer,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             ILogger<TmdbPersonProvider> logger)
         {
             _fileSystem = fileSystem;
             _configurationManager = configurationManager;
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
             Current = this;
         }
@@ -96,22 +97,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
 
             var url = string.Format(TmdbUtils.BaseTmdbApiUrl + @"3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), TmdbUtils.ApiKey);
 
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
+            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
 
-            }).ConfigureAwait(false))
-            {
-                using (var json = response.Content)
-                {
-                    var result = await _jsonSerializer.DeserializeFromStreamAsync<TmdbSearchResult<PersonSearchResult>>(json).ConfigureAwait(false) ??
-                                 new TmdbSearchResult<PersonSearchResult>();
+            var result2 = await _jsonSerializer.DeserializeFromStreamAsync<TmdbSearchResult<PersonSearchResult>>(stream).ConfigureAwait(false)
+                         ?? new TmdbSearchResult<PersonSearchResult>();
 
-                    return result.Results.Select(i => GetSearchResult(i, tmdbImageUrl));
-                }
-            }
+            return result2.Results.Select(i => GetSearchResult(i, tmdbImageUrl));
         }
 
         private RemoteSearchResult GetSearchResult(PersonSearchResult i, string baseImageUrl)
@@ -230,23 +224,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
 
             var url = string.Format(TmdbUtils.BaseTmdbApiUrl + @"3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", TmdbUtils.ApiKey, id);
 
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
-            }).ConfigureAwait(false))
-            {
-                using (var json = response.Content)
-                {
-                    Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
-
-                    using (var fs = new FileStream(dataFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true))
-                    {
-                        await json.CopyToAsync(fs).ConfigureAwait(false);
-                    }
-                }
-            }
+            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+            Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+            await using var fs = new FileStream(dataFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
+            await response.Content.CopyToAsync(fs).ConfigureAwait(false);
         }
 
         private static string GetPersonDataPath(IApplicationPaths appPaths, string tmdbId)
@@ -266,13 +249,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
             return Path.Combine(appPaths.CachePath, "tmdb-people");
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 4 - 4
MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs

@@ -3,9 +3,9 @@
 using System;
 using System.Collections.Generic;
 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;
@@ -26,8 +26,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
             IRemoteImageProvider,
             IHasOrder
     {
-        public TmdbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
-            : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory)
+        public TmdbEpisodeImageProvider(IHttpClientFactory httpClientFactory, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
+            : base(httpClientFactory, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory)
         { }
 
         public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
@@ -115,7 +115,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
             return images.Stills ?? new List<Still>();
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             return GetResponse(url, cancellationToken);
         }

+ 4 - 4
MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs

@@ -5,9 +5,9 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Net;
+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.TV;
@@ -27,8 +27,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
             IRemoteMetadataProvider<Episode, EpisodeInfo>,
             IHasOrder
     {
-        public TmdbEpisodeProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
-            : base(httpClient, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory)
+        public TmdbEpisodeProvider(IHttpClientFactory httpClientFactory, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
+            : base(httpClientFactory, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory)
         { }
 
         public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
@@ -201,7 +201,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
             return result;
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
             return GetResponse(url, cancellationToken);
         }

+ 12 - 22
MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs

@@ -3,9 +3,10 @@
 using System;
 using System.Globalization;
 using System.IO;
+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;
@@ -19,16 +20,16 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
     public abstract class TmdbEpisodeProviderBase
     {
         private const string EpisodeUrlPattern = TmdbUtils.BaseTmdbApiUrl + @"3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos";
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IServerConfigurationManager _configurationManager;
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IFileSystem _fileSystem;
         private readonly ILocalizationManager _localization;
         private readonly ILogger<TmdbEpisodeProviderBase> _logger;
 
-        protected TmdbEpisodeProviderBase(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
+        protected TmdbEpisodeProviderBase(IHttpClientFactory httpClientFactory, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _configurationManager = configurationManager;
             _jsonSerializer = jsonSerializer;
             _fileSystem = fileSystem;
@@ -124,27 +125,16 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
-            }).ConfigureAwait(false))
-            {
-                using (var json = response.Content)
-                {
-                    return await _jsonSerializer.DeserializeFromStreamAsync<EpisodeResult>(json).ConfigureAwait(false);
-                }
-            }
+            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            return await _jsonSerializer.DeserializeFromStreamAsync<EpisodeResult>(stream).ConfigureAwait(false);
         }
 
-        protected Task<HttpResponseInfo> GetResponse(string url, CancellationToken cancellationToken)
+        protected Task<HttpResponseMessage> GetResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 6 - 10
MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs

@@ -4,9 +4,9 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 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;
@@ -22,12 +22,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
     public class TmdbSeasonImageProvider : IRemoteImageProvider, IHasOrder
     {
         private readonly IJsonSerializer _jsonSerializer;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
 
-        public TmdbSeasonImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient)
+        public TmdbSeasonImageProvider(IJsonSerializer jsonSerializer, IHttpClientFactory httpClientFactory)
         {
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
         }
 
         public int Order => 1;
@@ -36,13 +36,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
 
         public static string ProviderName => TmdbUtils.ProviderName;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
 
         public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)

+ 12 - 22
MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs

@@ -5,9 +5,10 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Net;
+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;
@@ -26,7 +27,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
     public class TmdbSeasonProvider : IRemoteMetadataProvider<Season, SeasonInfo>
     {
         private const string GetTvInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/tv/{0}/season/{1}?api_key={2}&append_to_response=images,keywords,external_ids,credits,videos";
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IServerConfigurationManager _configurationManager;
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IFileSystem _fileSystem;
@@ -35,9 +36,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
 
         internal static TmdbSeasonProvider Current { get; private set; }
 
-        public TmdbSeasonProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILogger<TmdbSeasonProvider> logger)
+        public TmdbSeasonProvider(IHttpClientFactory httpClientFactory, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILogger<TmdbSeasonProvider> logger)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _configurationManager = configurationManager;
             _fileSystem = fileSystem;
             _localization = localization;
@@ -121,13 +122,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
             return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>());
         }
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
 
         private async Task<SeasonResult> GetSeasonInfo(string seriesTmdbId, int season, string preferredMetadataLanguage,
@@ -215,18 +212,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
-            }).ConfigureAwait(false))
-            {
-                using (var json = response.Content)
-                {
-                    return await _jsonSerializer.DeserializeFromStreamAsync<SeasonResult>(json).ConfigureAwait(false);
-                }
-            }
+            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            return await _jsonSerializer.DeserializeFromStreamAsync<SeasonResult>(stream).ConfigureAwait(false);
         }
     }
 }

+ 6 - 10
MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs

@@ -3,9 +3,9 @@
 using System;
 using System.Collections.Generic;
 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;
@@ -23,13 +23,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
     public class TmdbSeriesImageProvider : IRemoteImageProvider, IHasOrder
     {
         private readonly IJsonSerializer _jsonSerializer;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IFileSystem _fileSystem;
 
-        public TmdbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
+        public TmdbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClientFactory httpClientFactory, IFileSystem fileSystem)
         {
             _jsonSerializer = jsonSerializer;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _fileSystem = fileSystem;
         }
 
@@ -180,13 +180,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
         // After tvdb and fanart
         public int Order => 2;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 43 - 66
MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs

@@ -5,10 +5,11 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
+using System.Net.Http;
+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;
@@ -35,7 +36,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
         private readonly IServerConfigurationManager _configurationManager;
         private readonly ILogger<TmdbSeriesProvider> _logger;
         private readonly ILocalizationManager _localization;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILibraryManager _libraryManager;
 
         private readonly CultureInfo _usCulture = new CultureInfo("en-US");
@@ -48,7 +49,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
             IServerConfigurationManager configurationManager,
             ILogger<TmdbSeriesProvider> logger,
             ILocalizationManager localization,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             ILibraryManager libraryManager)
         {
             _jsonSerializer = jsonSerializer;
@@ -56,7 +57,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
             _configurationManager = configurationManager;
             _logger = logger;
             _localization = localization;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _libraryManager = libraryManager;
             Current = this;
         }
@@ -413,24 +414,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            SeriesResult mainResult;
+            using var mainRequestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+            mainRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var mainResponse = await TmdbMovieProvider.Current.GetMovieDbResponse(mainRequestMessage);
+            await using var mainStream = await mainResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            var mainResult = await _jsonSerializer.DeserializeFromStreamAsync<SeriesResult>(mainStream).ConfigureAwait(false);
 
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
-            }).ConfigureAwait(false))
+            if (!string.IsNullOrEmpty(language))
             {
-                using (var json = response.Content)
-                {
-                    mainResult = await _jsonSerializer.DeserializeFromStreamAsync<SeriesResult>(json).ConfigureAwait(false);
-
-                    if (!string.IsNullOrEmpty(language))
-                    {
-                        mainResult.ResultLanguage = language;
-                    }
-                }
+                mainResult.ResultLanguage = language;
             }
 
             cancellationToken.ThrowIfCancellationRequested();
@@ -451,21 +443,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
                     url += "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language);
                 }
 
-                using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-                {
-                    Url = url,
-                    CancellationToken = cancellationToken,
-                    AcceptHeader = TmdbUtils.AcceptHeader
-                }).ConfigureAwait(false))
-                {
-                    using (var json = response.Content)
-                    {
-                        var englishResult = await _jsonSerializer.DeserializeFromStreamAsync<SeriesResult>(json).ConfigureAwait(false);
+                using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+                requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+                using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage);
+                await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                var englishResult = await _jsonSerializer.DeserializeFromStreamAsync<SeriesResult>(stream).ConfigureAwait(false);
 
-                        mainResult.Overview = englishResult.Overview;
-                        mainResult.ResultLanguage = "en";
-                    }
-                }
+                mainResult.Overview = englishResult.Overview;
+                mainResult.ResultLanguage = "en";
             }
 
             return mainResult;
@@ -515,38 +500,34 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
                 TmdbUtils.ApiKey,
                 externalSource);
 
-            using (var response = await TmdbMovieProvider.Current.GetMovieDbResponse(new HttpRequestOptions
-            {
-                Url = url,
-                CancellationToken = cancellationToken,
-                AcceptHeader = TmdbUtils.AcceptHeader
-            }).ConfigureAwait(false))
+            using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url);
+            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(TmdbUtils.AcceptHeader));
+            using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+
+            var result = await _jsonSerializer.DeserializeFromStreamAsync<ExternalIdLookupResult>(stream).ConfigureAwait(false);
+
+            if (result != null && result.Tv_Results != null)
             {
-                using (var json = response.Content)
+                var tv = result.Tv_Results.FirstOrDefault();
+
+                if (tv != null)
                 {
-                    var result = await _jsonSerializer.DeserializeFromStreamAsync<ExternalIdLookupResult>(json).ConfigureAwait(false);
+                    var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+                    var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
 
-                    if (result != null && result.Tv_Results != null)
+                    var remoteResult = new RemoteSearchResult
                     {
-                        var tv = result.Tv_Results.FirstOrDefault();
-
-                        if (tv != null)
-                        {
-                            var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
-                            var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original");
-
-                            var remoteResult = new RemoteSearchResult
-                            {
-                                Name = tv.Name,
-                                SearchProviderName = Name,
-                                ImageUrl = string.IsNullOrWhiteSpace(tv.Poster_Path) ? null : tmdbImageUrl + tv.Poster_Path
-                            };
+                        Name = tv.Name,
+                        SearchProviderName = Name,
+                        ImageUrl = string.IsNullOrWhiteSpace(tv.Poster_Path)
+                            ? null
+                            : tmdbImageUrl + tv.Poster_Path
+                    };
 
-                            remoteResult.SetProviderId(MetadataProvider.Tmdb, tv.Id.ToString(_usCulture));
+                    remoteResult.SetProviderId(MetadataProvider.Tmdb, tv.Id.ToString(_usCulture));
 
-                            return remoteResult;
-                        }
-                    }
+                    return remoteResult;
                 }
             }
 
@@ -556,13 +537,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
         // After TheTVDB
         public int Order => 1;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 6 - 10
MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs

@@ -1,9 +1,9 @@
 #pragma warning disable CS1591
 
 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;
@@ -13,11 +13,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Trailers
 {
     public class TmdbTrailerProvider : IHasOrder, IRemoteMetadataProvider<Trailer, TrailerInfo>
     {
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
 
-        public TmdbTrailerProvider(IHttpClient httpClient)
+        public TmdbTrailerProvider(IHttpClientFactory httpClientFactory)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
         }
 
         public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
@@ -34,13 +34,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Trailers
 
         public int Order => 0;
 
-        public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+        public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
         {
-            return _httpClient.GetResponse(new HttpRequestOptions
-            {
-                CancellationToken = cancellationToken,
-                Url = url
-            });
+            return _httpClientFactory.CreateClient().GetAsync(url, cancellationToken);
         }
     }
 }

+ 0 - 1
MediaBrowser.Providers/Studios/StudiosImageProvider.cs

@@ -7,7 +7,6 @@ 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;