浏览代码

migrate to IHttpClientFactory in Emby.Dlna

crobibero 4 年之前
父节点
当前提交
8215f15c45

+ 3 - 3
Emby.Dlna/ConnectionManager/ConnectionManagerService.cs

@@ -1,8 +1,8 @@
 #pragma warning disable CS1591
 
+using System.Net.Http;
 using System.Threading.Tasks;
 using Emby.Dlna.Service;
-using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Dlna;
 using Microsoft.Extensions.Logging;
@@ -18,8 +18,8 @@ namespace Emby.Dlna.ConnectionManager
             IDlnaManager dlna,
             IServerConfigurationManager config,
             ILogger<ConnectionManagerService> logger,
-            IHttpClient httpClient)
-            : base(logger, httpClient)
+            IHttpClientFactory httpClientFactory)
+            : base(logger, httpClientFactory)
         {
             _dlna = dlna;
             _config = config;

+ 2 - 2
Emby.Dlna/ContentDirectory/ContentDirectoryService.cs

@@ -2,11 +2,11 @@
 
 using System;
 using System.Linq;
+using System.Net.Http;
 using System.Threading.Tasks;
 using Emby.Dlna.Service;
 using Jellyfin.Data.Entities;
 using Jellyfin.Data.Enums;
-using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Dlna;
 using MediaBrowser.Controller.Drawing;
@@ -41,7 +41,7 @@ namespace Emby.Dlna.ContentDirectory
             IServerConfigurationManager config,
             IUserManager userManager,
             ILogger<ContentDirectoryService> logger,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClient,
             ILocalizationManager localization,
             IMediaSourceManager mediaSourceManager,
             IUserViewManager userViewManager,

+ 1 - 0
Emby.Dlna/Emby.Dlna.csproj

@@ -80,6 +80,7 @@
   <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
     <PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
+    <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" />
   </ItemGroup>
 
 </Project>

+ 12 - 18
Emby.Dlna/Eventing/DlnaEventManager.cs

@@ -6,6 +6,7 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Net.Http;
+using System.Net.Mime;
 using System.Text;
 using System.Threading.Tasks;
 using MediaBrowser.Common.Extensions;
@@ -20,13 +21,13 @@ namespace Emby.Dlna.Eventing
             new ConcurrentDictionary<string, EventSubscription>(StringComparer.OrdinalIgnoreCase);
 
         private readonly ILogger _logger;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
 
         private readonly CultureInfo _usCulture = new CultureInfo("en-US");
 
-        public DlnaEventManager(ILogger logger, IHttpClient httpClient)
+        public DlnaEventManager(ILogger logger, IHttpClientFactory httpClientFactory)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
         }
 
@@ -167,24 +168,17 @@ namespace Emby.Dlna.Eventing
 
             builder.Append("</e:propertyset>");
 
-            var options = new HttpRequestOptions
-            {
-                RequestContent = builder.ToString(),
-                RequestContentType = "text/xml",
-                Url = subscription.CallbackUrl,
-                BufferContent = false
-            };
-
-            options.RequestHeaders.Add("NT", subscription.NotificationType);
-            options.RequestHeaders.Add("NTS", "upnp:propchange");
-            options.RequestHeaders.Add("SID", subscription.Id);
-            options.RequestHeaders.Add("SEQ", subscription.TriggerCount.ToString(_usCulture));
+            using var options = new HttpRequestMessage(new HttpMethod("NOTIFY"),  subscription.CallbackUrl);
+            options.Content = new StringContent(builder.ToString(), Encoding.UTF8, MediaTypeNames.Text.Xml);
+            options.Headers.TryAddWithoutValidation("NT", subscription.NotificationType);
+            options.Headers.TryAddWithoutValidation("NTS", "upnp:propchange");
+            options.Headers.TryAddWithoutValidation("SID", subscription.Id);
+            options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(_usCulture));
 
             try
             {
-                using (await _httpClient.SendAsync(options, new HttpMethod("NOTIFY")).ConfigureAwait(false))
-                {
-                }
+                await _httpClientFactory.CreateClient(NamedClient.Default)
+                    .SendAsync(options).ConfigureAwait(false);
             }
             catch (OperationCanceledException)
             {

+ 8 - 7
Emby.Dlna/Main/DlnaEntryPoint.cs

@@ -2,6 +2,7 @@
 
 using System;
 using System.Globalization;
+using System.Net.Http;
 using System.Net.Sockets;
 using System.Threading;
 using System.Threading.Tasks;
@@ -36,7 +37,7 @@ namespace Emby.Dlna.Main
         private readonly ILogger<DlnaEntryPoint> _logger;
         private readonly IServerApplicationHost _appHost;
         private readonly ISessionManager _sessionManager;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly ILibraryManager _libraryManager;
         private readonly IUserManager _userManager;
         private readonly IDlnaManager _dlnaManager;
@@ -61,7 +62,7 @@ namespace Emby.Dlna.Main
             ILoggerFactory loggerFactory,
             IServerApplicationHost appHost,
             ISessionManager sessionManager,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             ILibraryManager libraryManager,
             IUserManager userManager,
             IDlnaManager dlnaManager,
@@ -79,7 +80,7 @@ namespace Emby.Dlna.Main
             _config = config;
             _appHost = appHost;
             _sessionManager = sessionManager;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _libraryManager = libraryManager;
             _userManager = userManager;
             _dlnaManager = dlnaManager;
@@ -101,7 +102,7 @@ namespace Emby.Dlna.Main
                 config,
                 userManager,
                 loggerFactory.CreateLogger<ContentDirectory.ContentDirectoryService>(),
-                httpClient,
+                httpClientFactory,
                 localizationManager,
                 mediaSourceManager,
                 userViewManager,
@@ -112,11 +113,11 @@ namespace Emby.Dlna.Main
                 dlnaManager,
                 config,
                 loggerFactory.CreateLogger<ConnectionManager.ConnectionManagerService>(),
-                httpClient);
+                httpClientFactory);
 
             MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrarService(
                 loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrarService>(),
-                httpClient,
+                httpClientFactory,
                 config);
             Current = this;
         }
@@ -364,7 +365,7 @@ namespace Emby.Dlna.Main
                         _appHost,
                         _imageProcessor,
                         _deviceDiscovery,
-                        _httpClient,
+                        _httpClientFactory,
                         _config,
                         _userDataManager,
                         _localization,

+ 3 - 3
Emby.Dlna/MediaReceiverRegistrar/MediaReceiverRegistrarService.cs

@@ -1,8 +1,8 @@
 #pragma warning disable CS1591
 
+using System.Net.Http;
 using System.Threading.Tasks;
 using Emby.Dlna.Service;
-using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Configuration;
 using Microsoft.Extensions.Logging;
 
@@ -14,9 +14,9 @@ namespace Emby.Dlna.MediaReceiverRegistrar
 
         public MediaReceiverRegistrarService(
             ILogger<MediaReceiverRegistrarService> logger,
-            IHttpClient httpClient,
+            IHttpClientFactory httpClientFactory,
             IServerConfigurationManager config)
-            : base(logger, httpClient)
+            : base(logger, httpClientFactory)
         {
             _config = config;
         }

+ 21 - 20
Emby.Dlna/PlayTo/Device.cs

@@ -4,6 +4,7 @@ using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
+using System.Net.Http;
 using System.Security;
 using System.Threading;
 using System.Threading.Tasks;
@@ -21,7 +22,7 @@ namespace Emby.Dlna.PlayTo
     {
         private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
 
         private readonly ILogger _logger;
 
@@ -34,10 +35,10 @@ namespace Emby.Dlna.PlayTo
         private int _connectFailureCount;
         private bool _disposed;
 
-        public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger)
+        public Device(DeviceInfo deviceProperties, IHttpClientFactory httpClientFactory, ILogger logger)
         {
             Properties = deviceProperties;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _logger = logger;
         }
 
@@ -236,7 +237,7 @@ namespace Emby.Dlna.PlayTo
             _logger.LogDebug("Setting mute");
             var value = mute ? 1 : 0;
 
-            await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
+            await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
                 .ConfigureAwait(false);
 
             IsMuted = mute;
@@ -271,7 +272,7 @@ namespace Emby.Dlna.PlayTo
             // Remote control will perform better
             Volume = value;
 
-            await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
+            await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
                 .ConfigureAwait(false);
         }
 
@@ -292,7 +293,7 @@ namespace Emby.Dlna.PlayTo
                 throw new InvalidOperationException("Unable to find service");
             }
 
-            await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME"))
+            await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME"))
                 .ConfigureAwait(false);
 
             RestartTimer(true);
@@ -326,7 +327,7 @@ namespace Emby.Dlna.PlayTo
             }
 
             var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
-            await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header)
+            await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header)
                 .ConfigureAwait(false);
 
             await Task.Delay(50).ConfigureAwait(false);
@@ -368,7 +369,7 @@ namespace Emby.Dlna.PlayTo
                 throw new InvalidOperationException("Unable to find service");
             }
 
-            return new SsdpHttpClient(_httpClient).SendCommandAsync(
+            return new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 service,
                 command.Name,
@@ -397,7 +398,7 @@ namespace Emby.Dlna.PlayTo
 
             var service = GetAvTransportService();
 
-            await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
+            await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
                 .ConfigureAwait(false);
 
             RestartTimer(true);
@@ -415,7 +416,7 @@ namespace Emby.Dlna.PlayTo
 
             var service = GetAvTransportService();
 
-            await new SsdpHttpClient(_httpClient).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
+            await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
                 .ConfigureAwait(false);
 
             TransportState = TransportState.Paused;
@@ -542,7 +543,7 @@ namespace Emby.Dlna.PlayTo
                 return;
             }
 
-            var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
+            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 service,
                 command.Name,
@@ -592,7 +593,7 @@ namespace Emby.Dlna.PlayTo
                 return;
             }
 
-            var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
+            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 service,
                 command.Name,
@@ -625,7 +626,7 @@ namespace Emby.Dlna.PlayTo
                 return null;
             }
 
-            var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
+            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 service,
                 command.Name,
@@ -667,7 +668,7 @@ namespace Emby.Dlna.PlayTo
 
             var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
 
-            var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
+            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 service,
                 command.Name,
@@ -734,7 +735,7 @@ namespace Emby.Dlna.PlayTo
 
             var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
 
-            var result = await new SsdpHttpClient(_httpClient).SendCommandAsync(
+            var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
                 Properties.BaseUrl,
                 service,
                 command.Name,
@@ -912,7 +913,7 @@ namespace Emby.Dlna.PlayTo
 
             string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
 
-            var httpClient = new SsdpHttpClient(_httpClient);
+            var httpClient = new SsdpHttpClient(_httpClientFactory);
 
             var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
 
@@ -940,7 +941,7 @@ namespace Emby.Dlna.PlayTo
 
             string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
 
-            var httpClient = new SsdpHttpClient(_httpClient);
+            var httpClient = new SsdpHttpClient(_httpClientFactory);
             _logger.LogDebug("Dlna Device.GetRenderingProtocolAsync");
             var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
 
@@ -969,9 +970,9 @@ namespace Emby.Dlna.PlayTo
             return baseUrl + url;
         }
 
-        public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, ILogger logger, CancellationToken cancellationToken)
+        public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClientFactory httpClientFactory, ILogger logger, CancellationToken cancellationToken)
         {
-            var ssdpHttpClient = new SsdpHttpClient(httpClient);
+            var ssdpHttpClient = new SsdpHttpClient(httpClientFactory);
 
             var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
 
@@ -1079,7 +1080,7 @@ namespace Emby.Dlna.PlayTo
                 }
             }
 
-            return new Device(deviceProperties, httpClient, logger);
+            return new Device(deviceProperties, httpClientFactory, logger);
         }
 
         private static DeviceIcon CreateIcon(XElement element)

+ 5 - 4
Emby.Dlna/PlayTo/PlayToManager.cs

@@ -4,6 +4,7 @@ using System;
 using System.Globalization;
 using System.Linq;
 using System.Net;
+using System.Net.Http;
 using System.Threading;
 using System.Threading.Tasks;
 using Jellyfin.Data.Events;
@@ -33,7 +34,7 @@ namespace Emby.Dlna.PlayTo
         private readonly IDlnaManager _dlnaManager;
         private readonly IServerApplicationHost _appHost;
         private readonly IImageProcessor _imageProcessor;
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
         private readonly IServerConfigurationManager _config;
         private readonly IUserDataManager _userDataManager;
         private readonly ILocalizationManager _localization;
@@ -46,7 +47,7 @@ namespace Emby.Dlna.PlayTo
         private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
         private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
 
-        public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder)
+        public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClientFactory httpClientFactory, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder)
         {
             _logger = logger;
             _sessionManager = sessionManager;
@@ -56,7 +57,7 @@ namespace Emby.Dlna.PlayTo
             _appHost = appHost;
             _imageProcessor = imageProcessor;
             _deviceDiscovery = deviceDiscovery;
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
             _config = config;
             _userDataManager = userDataManager;
             _localization = localization;
@@ -174,7 +175,7 @@ namespace Emby.Dlna.PlayTo
 
             if (controller == null)
             {
-                var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _logger, cancellationToken).ConfigureAwait(false);
+                var device = await Device.CreateuPnpDeviceAsync(uri, _httpClientFactory, _logger, cancellationToken).ConfigureAwait(false);
 
                 string deviceName = device.Properties.Name;
 

+ 45 - 71
Emby.Dlna/PlayTo/SsdpHttpClient.cs

@@ -4,6 +4,8 @@ using System;
 using System.Globalization;
 using System.IO;
 using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Net.Mime;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
@@ -20,11 +22,11 @@ namespace Emby.Dlna.PlayTo
 
         private readonly CultureInfo _usCulture = new CultureInfo("en-US");
 
-        private readonly IHttpClient _httpClient;
+        private readonly IHttpClientFactory _httpClientFactory;
 
-        public SsdpHttpClient(IHttpClient httpClient)
+        public SsdpHttpClient(IHttpClientFactory httpClientFactory)
         {
-            _httpClient = httpClient;
+            _httpClientFactory = httpClientFactory;
         }
 
         public async Task<XDocument> SendCommandAsync(
@@ -36,20 +38,18 @@ namespace Emby.Dlna.PlayTo
             CancellationToken cancellationToken = default)
         {
             var url = NormalizeServiceUrl(baseUrl, service.ControlUrl);
-            using (var response = await PostSoapDataAsync(
-                url,
-                $"\"{service.ServiceType}#{command}\"",
-                postData,
-                header,
-                cancellationToken)
-                .ConfigureAwait(false))
-            using (var stream = response.Content)
-            using (var reader = new StreamReader(stream, Encoding.UTF8))
-            {
-                return XDocument.Parse(
-                    await reader.ReadToEndAsync().ConfigureAwait(false),
-                    LoadOptions.PreserveWhitespace);
-            }
+            using var response = await PostSoapDataAsync(
+                    url,
+                    $"\"{service.ServiceType}#{command}\"",
+                    postData,
+                    header,
+                    cancellationToken)
+                .ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            using var reader = new StreamReader(stream, Encoding.UTF8);
+            return XDocument.Parse(
+                await reader.ReadToEndAsync().ConfigureAwait(false),
+                LoadOptions.PreserveWhitespace);
         }
 
         private static string NormalizeServiceUrl(string baseUrl, string serviceUrl)
@@ -76,49 +76,32 @@ namespace Emby.Dlna.PlayTo
             int eventport,
             int timeOut = 3600)
         {
-            var options = new HttpRequestOptions
-            {
-                Url = url,
-                UserAgent = USERAGENT,
-                LogErrorResponseBody = true,
-                BufferContent = false,
-            };
-
-            options.RequestHeaders["HOST"] = ip + ":" + port.ToString(_usCulture);
-            options.RequestHeaders["CALLBACK"] = "<" + localIp + ":" + eventport.ToString(_usCulture) + ">";
-            options.RequestHeaders["NT"] = "upnp:event";
-            options.RequestHeaders["TIMEOUT"] = "Second-" + timeOut.ToString(_usCulture);
-
-            using (await _httpClient.SendAsync(options, new HttpMethod("SUBSCRIBE")).ConfigureAwait(false))
-            {
-            }
+            using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url);
+            options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT));
+            options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture));
+            options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">");
+            options.Headers.TryAddWithoutValidation("NT", "upnp:event");
+            options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture));
+
+            using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
+                .SendAsync(options)
+                .ConfigureAwait(false);
         }
 
         public async Task<XDocument> GetDataAsync(string url, CancellationToken cancellationToken)
         {
-            var options = new HttpRequestOptions
-            {
-                Url = url,
-                UserAgent = USERAGENT,
-                LogErrorResponseBody = true,
-                BufferContent = false,
-
-                CancellationToken = cancellationToken
-            };
-
-            options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
-
-            using (var response = await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false))
-            using (var stream = response.Content)
-            using (var reader = new StreamReader(stream, Encoding.UTF8))
-            {
-                return XDocument.Parse(
-                    await reader.ReadToEndAsync().ConfigureAwait(false),
-                    LoadOptions.PreserveWhitespace);
-            }
+            using var options = new HttpRequestMessage(HttpMethod.Get, url);
+            options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT));
+            options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
+            using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken).ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            using var reader = new StreamReader(stream, Encoding.UTF8);
+            return XDocument.Parse(
+                await reader.ReadToEndAsync().ConfigureAwait(false),
+                LoadOptions.PreserveWhitespace);
         }
 
-        private Task<HttpResponseInfo> PostSoapDataAsync(
+        private Task<HttpResponseMessage> PostSoapDataAsync(
             string url,
             string soapAction,
             string postData,
@@ -130,29 +113,20 @@ namespace Emby.Dlna.PlayTo
                 soapAction = $"\"{soapAction}\"";
             }
 
-            var options = new HttpRequestOptions
-            {
-                Url = url,
-                UserAgent = USERAGENT,
-                LogErrorResponseBody = true,
-                BufferContent = false,
-
-                CancellationToken = cancellationToken
-            };
-
-            options.RequestHeaders["SOAPAction"] = soapAction;
-            options.RequestHeaders["Pragma"] = "no-cache";
-            options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
+            using var options = new HttpRequestMessage(HttpMethod.Post, url);
+            options.Headers.UserAgent.Add(ProductInfoHeaderValue.Parse(USERAGENT));
+            options.Headers.TryAddWithoutValidation("SOAPACTION", soapAction);
+            options.Headers.TryAddWithoutValidation("Pragma", "no-cache");
+            options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
 
             if (!string.IsNullOrEmpty(header))
             {
-                options.RequestHeaders["contentFeatures.dlna.org"] = header;
+                options.Headers.TryAddWithoutValidation("contentFeatures.dlna.org", header);
             }
 
-            options.RequestContentType = "text/xml";
-            options.RequestContent = postData;
+            options.Content = new StringContent(postData, Encoding.UTF8, MediaTypeNames.Text.Xml);
 
-            return _httpClient.Post(options);
+            return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, cancellationToken);
         }
     }
 }

+ 3 - 7
Emby.Dlna/Service/BaseService.cs

@@ -1,25 +1,21 @@
 #pragma warning disable CS1591
 
+using System.Net.Http;
 using Emby.Dlna.Eventing;
-using MediaBrowser.Common.Net;
 using Microsoft.Extensions.Logging;
 
 namespace Emby.Dlna.Service
 {
     public class BaseService : IDlnaEventManager
     {
-        protected BaseService(ILogger<BaseService> logger, IHttpClient httpClient)
+        protected BaseService(ILogger<BaseService> logger, IHttpClientFactory httpClientFactory)
         {
             Logger = logger;
-            HttpClient = httpClient;
-
-            EventManager = new DlnaEventManager(logger, HttpClient);
+            EventManager = new DlnaEventManager(logger, httpClientFactory);
         }
 
         protected IDlnaEventManager EventManager { get; }
 
-        protected IHttpClient HttpClient { get; }
-
         protected ILogger Logger { get; }
 
         public EventSubscriptionResponse CancelEventSubscription(string subscriptionId)