Преглед изворни кода

Pass cancellation where possible

Bond_009 пре 4 година
родитељ
комит
4b1c9dc9ea

+ 2 - 2
Emby.Dlna/PlayTo/SsdpHttpClient.cs

@@ -45,7 +45,7 @@ namespace Emby.Dlna.PlayTo
                     header,
                     header,
                     cancellationToken)
                     cancellationToken)
                 .ConfigureAwait(false);
                 .ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             using var reader = new StreamReader(stream, Encoding.UTF8);
             using var reader = new StreamReader(stream, Encoding.UTF8);
             return XDocument.Parse(
             return XDocument.Parse(
                 await reader.ReadToEndAsync().ConfigureAwait(false),
                 await reader.ReadToEndAsync().ConfigureAwait(false),
@@ -94,7 +94,7 @@ namespace Emby.Dlna.PlayTo
             options.Headers.UserAgent.ParseAdd(USERAGENT);
             options.Headers.UserAgent.ParseAdd(USERAGENT);
             options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
             options.Headers.TryAddWithoutValidation("FriendlyName.DLNA.ORG", FriendlyName);
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             using var reader = new StreamReader(stream, Encoding.UTF8);
             using var reader = new StreamReader(stream, Encoding.UTF8);
             return XDocument.Parse(
             return XDocument.Parse(
                 await reader.ReadToEndAsync().ConfigureAwait(false),
                 await reader.ReadToEndAsync().ConfigureAwait(false),

+ 1 - 1
Emby.Server.Implementations/ApplicationHost.cs

@@ -1378,7 +1378,7 @@ namespace Emby.Server.Implementations
                 using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                 using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                     .SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
                     .SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
 
 
-                await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                 var result = await System.Text.Json.JsonSerializer.DeserializeAsync<string>(stream, JsonDefaults.GetOptions(), cancellationToken).ConfigureAwait(false);
                 var result = await System.Text.Json.JsonSerializer.DeserializeAsync<string>(stream, JsonDefaults.GetOptions(), cancellationToken).ConfigureAwait(false);
                 var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
                 var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase);
 
 

+ 0 - 14
Emby.Server.Implementations/Data/SqliteExtensions.cs

@@ -107,20 +107,6 @@ namespace Emby.Server.Implementations.Data
             return null;
             return null;
         }
         }
 
 
-        public static void Attach(SQLiteDatabaseConnection db, string path, string alias)
-        {
-            var commandText = string.Format(
-                CultureInfo.InvariantCulture,
-                "attach @path as {0};",
-                alias);
-
-            using (var statement = db.PrepareStatement(commandText))
-            {
-                statement.TryBind("@path", path);
-                statement.MoveNext();
-            }
-        }
-
         public static bool IsDBNull(this IReadOnlyList<IResultSetValue> result, int index)
         public static bool IsDBNull(this IReadOnlyList<IResultSetValue> result, int index)
         {
         {
             return result[index].SQLiteType == SQLiteType.Null;
             return result[index].SQLiteType == SQLiteType.Null;

+ 4 - 3
Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs

@@ -77,11 +77,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
             _logger.LogInformation("Copying recording stream to file {0}", targetFile);
             _logger.LogInformation("Copying recording stream to file {0}", targetFile);
 
 
             // The media source if infinite so we need to handle stopping ourselves
             // The media source if infinite so we need to handle stopping ourselves
-            var durationToken = new CancellationTokenSource(duration);
-            cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
+            using var durationToken = new CancellationTokenSource(duration);
+            using var linkedCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
+            cancellationToken = linkedCancellationToken.Token;
 
 
             await _streamHelper.CopyUntilCancelled(
             await _streamHelper.CopyUntilCancelled(
-                await response.Content.ReadAsStreamAsync().ConfigureAwait(false),
+                await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false),
                 output,
                 output,
                 IODefaults.CopyToBufferSize,
                 IODefaults.CopyToBufferSize,
                 cancellationToken).ConfigureAwait(false);
                 cancellationToken).ConfigureAwait(false);

+ 9 - 9
Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs

@@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             options.Content = new StringContent(requestString, Encoding.UTF8, MediaTypeNames.Application.Json);
             options.Content = new StringContent(requestString, Encoding.UTF8, MediaTypeNames.Application.Json);
             options.Headers.TryAddWithoutValidation("token", token);
             options.Headers.TryAddWithoutValidation("token", token);
             using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false);
             using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false);
-            await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Day>>(responseStream).ConfigureAwait(false);
             var dailySchedules = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Day>>(responseStream).ConfigureAwait(false);
             _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId);
             _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId);
 
 
@@ -123,7 +123,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programsID) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json);
             programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programsID) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json);
 
 
             using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false);
             using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false);
-            await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             var programDetails = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ProgramDetails>>(innerResponseStream).ConfigureAwait(false);
             var programDetails = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ProgramDetails>>(innerResponseStream).ConfigureAwait(false);
             var programDict = programDetails.ToDictionary(p => p.programID, y => y);
             var programDict = programDetails.ToDictionary(p => p.programID, y => y);
 
 
@@ -480,9 +480,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             try
             try
             {
             {
                 using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false);
                 using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false);
-                await using var response = await innerResponse2.Content.ReadAsStreamAsync().ConfigureAwait(false);
-                return await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ShowImages>>(
-                    response).ConfigureAwait(false);
+                await using var response = await innerResponse2.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+                return await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.ShowImages>>(response).ConfigureAwait(false);
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
@@ -509,7 +508,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             try
             try
             {
             {
                 using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false);
                 using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false);
-                await using var response = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                await using var response = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
 
 
                 var root = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Headends>>(response).ConfigureAwait(false);
                 var root = await _jsonSerializer.DeserializeFromStreamAsync<List<ScheduleDirect.Headends>>(response).ConfigureAwait(false);
 
 
@@ -542,6 +541,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
 
         private readonly ConcurrentDictionary<string, NameValuePair> _tokens = new ConcurrentDictionary<string, NameValuePair>();
         private readonly ConcurrentDictionary<string, NameValuePair> _tokens = new ConcurrentDictionary<string, NameValuePair>();
         private DateTime _lastErrorResponse;
         private DateTime _lastErrorResponse;
+
         private async Task<string> GetToken(ListingsProviderInfo info, CancellationToken cancellationToken)
         private async Task<string> GetToken(ListingsProviderInfo info, CancellationToken cancellationToken)
         {
         {
             var username = info.Username;
             var username = info.Username;
@@ -651,7 +651,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             options.Content = new StringContent("{\"username\":\"" + username + "\",\"password\":\"" + hashedPassword + "\"}", Encoding.UTF8, MediaTypeNames.Application.Json);
             options.Content = new StringContent("{\"username\":\"" + username + "\",\"password\":\"" + hashedPassword + "\"}", Encoding.UTF8, MediaTypeNames.Application.Json);
 
 
             using var response = await Send(options, false, null, cancellationToken).ConfigureAwait(false);
             using var response = await Send(options, false, null, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Token>(stream).ConfigureAwait(false);
             var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Token>(stream).ConfigureAwait(false);
             if (root.message == "OK")
             if (root.message == "OK")
             {
             {
@@ -705,7 +705,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             try
             try
             {
             {
                 using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false);
                 using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false);
-                await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                 using var response = httpResponse.Content;
                 using var response = httpResponse.Content;
                 var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Lineups>(stream).ConfigureAwait(false);
                 var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Lineups>(stream).ConfigureAwait(false);
 
 
@@ -780,7 +780,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             var list = new List<ChannelInfo>();
             var list = new List<ChannelInfo>();
 
 
             using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false);
             using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false);
-            await using var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Channel>(stream).ConfigureAwait(false);
             var root = await _jsonSerializer.DeserializeFromStreamAsync<ScheduleDirect.Channel>(stream).ConfigureAwait(false);
             _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count);
             _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.map.Count);
             _logger.LogInformation("Mapping Stations to Channel");
             _logger.LogInformation("Mapping Stations to Channel");

+ 1 - 1
Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs

@@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
             Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));
             Directory.CreateDirectory(Path.GetDirectoryName(cacheFile));
 
 
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false);
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew))
             await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew))
             {
             {
                 await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
                 await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);

+ 3 - 3
Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs

@@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
             var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
 
 
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             var lineup = await JsonSerializer.DeserializeAsync<List<Channels>>(stream, cancellationToken: cancellationToken)
             var lineup = await JsonSerializer.DeserializeAsync<List<Channels>>(stream, cancellationToken: cancellationToken)
                 .ConfigureAwait(false) ?? new List<Channels>();
                 .ConfigureAwait(false) ?? new List<Channels>();
 
 
@@ -129,7 +129,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
                 using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                 using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                     .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken)
                     .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/discover.json", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken)
                     .ConfigureAwait(false);
                     .ConfigureAwait(false);
-                await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                 var discoverResponse = await JsonSerializer.DeserializeAsync<DiscoverResponse>(stream, cancellationToken: cancellationToken)
                 var discoverResponse = await JsonSerializer.DeserializeAsync<DiscoverResponse>(stream, cancellationToken: cancellationToken)
                     .ConfigureAwait(false);
                     .ConfigureAwait(false);
 
 
@@ -175,7 +175,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                 .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken)
                 .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken)
                 .ConfigureAwait(false);
                 .ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             using var sr = new StreamReader(stream, System.Text.Encoding.UTF8);
             using var sr = new StreamReader(stream, System.Text.Encoding.UTF8);
             var tuners = new List<LiveTvTunerInfo>();
             var tuners = new List<LiveTvTunerInfo>();
             while (!sr.EndOfStream)
             while (!sr.EndOfStream)

+ 1 - 1
Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs

@@ -63,7 +63,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                     .SendAsync(requestMessage, cancellationToken)
                     .SendAsync(requestMessage, cancellationToken)
                     .ConfigureAwait(false);
                     .ConfigureAwait(false);
                 response.EnsureSuccessStatusCode();
                 response.EnsureSuccessStatusCode();
-                return await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                return await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             }
             }
 
 
             return File.OpenRead(info.Url);
             return File.OpenRead(info.Url);

+ 1 - 1
Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs

@@ -135,7 +135,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
                 {
                 {
                     Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath);
                     Logger.LogInformation("Beginning {0} stream to {1}", GetType().Name, TempFilePath);
                     using var message = response;
                     using var message = response;
-                    await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                    await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                     await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read);
                     await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read);
                     await StreamHelper.CopyToAsync(
                     await StreamHelper.CopyToAsync(
                         stream,
                         stream,

+ 4 - 3
Emby.Server.Implementations/Updates/InstallationManager.cs

@@ -99,7 +99,7 @@ namespace Emby.Server.Implementations.Updates
             {
             {
                 using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                 using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                     .GetAsync(manifest, cancellationToken).ConfigureAwait(false);
                     .GetAsync(manifest, cancellationToken).ConfigureAwait(false);
-                await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
 
 
                 try
                 try
                 {
                 {
@@ -241,7 +241,8 @@ namespace Emby.Server.Implementations.Updates
                 _currentInstallations.Add(tuple);
                 _currentInstallations.Add(tuple);
             }
             }
 
 
-            var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token;
+            using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token);
+            var linkedToken = linkedTokenSource.Token;
 
 
             await _eventManager.PublishAsync(new PluginInstallingEventArgs(package)).ConfigureAwait(false);
             await _eventManager.PublishAsync(new PluginInstallingEventArgs(package)).ConfigureAwait(false);
 
 
@@ -333,7 +334,7 @@ namespace Emby.Server.Implementations.Updates
 
 
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                 .GetAsync(package.SourceUrl, cancellationToken).ConfigureAwait(false);
                 .GetAsync(package.SourceUrl, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
 
 
             // CA5351: Do Not Use Broken Cryptographic Algorithms
             // CA5351: Do Not Use Broken Cryptographic Algorithms
 #pragma warning disable CA5351
 #pragma warning disable CA5351

+ 4 - 2
Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs

@@ -24,12 +24,14 @@ namespace Jellyfin.Api.Helpers
         /// <param name="isHeadRequest">Whether the current request is a HTTP HEAD request so only the headers get returned.</param>
         /// <param name="isHeadRequest">Whether the current request is a HTTP HEAD request so only the headers get returned.</param>
         /// <param name="httpClient">The <see cref="HttpClient"/> making the remote request.</param>
         /// <param name="httpClient">The <see cref="HttpClient"/> making the remote request.</param>
         /// <param name="httpContext">The current http context.</param>
         /// <param name="httpContext">The current http context.</param>
+        /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
         /// <returns>A <see cref="Task{ActionResult}"/> containing the API response.</returns>
         /// <returns>A <see cref="Task{ActionResult}"/> containing the API response.</returns>
         public static async Task<ActionResult> GetStaticRemoteStreamResult(
         public static async Task<ActionResult> GetStaticRemoteStreamResult(
             StreamState state,
             StreamState state,
             bool isHeadRequest,
             bool isHeadRequest,
             HttpClient httpClient,
             HttpClient httpClient,
-            HttpContext httpContext)
+            HttpContext httpContext,
+            CancellationToken cancellationToken = default)
         {
         {
             if (state.RemoteHttpHeaders.TryGetValue(HeaderNames.UserAgent, out var useragent))
             if (state.RemoteHttpHeaders.TryGetValue(HeaderNames.UserAgent, out var useragent))
             {
             {
@@ -47,7 +49,7 @@ namespace Jellyfin.Api.Helpers
                 return new FileContentResult(Array.Empty<byte>(), contentType);
                 return new FileContentResult(Array.Empty<byte>(), contentType);
             }
             }
 
 
-            return new FileStreamResult(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), contentType);
+            return new FileStreamResult(await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false), contentType);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs

@@ -760,7 +760,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                     using var response = await _httpClientFactory.CreateClient(NamedClient.Default)
                         .GetAsync(new Uri(path), cancellationToken)
                         .GetAsync(new Uri(path), cancellationToken)
                         .ConfigureAwait(false);
                         .ConfigureAwait(false);
-                    return await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                    return await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                 }
                 }
 
 
                 case MediaProtocol.File:
                 case MediaProtocol.File:

+ 2 - 2
MediaBrowser.Providers/Manager/ItemImageProvider.cs

@@ -469,7 +469,7 @@ namespace MediaBrowser.Providers.Manager
                 try
                 try
                 {
                 {
                     using var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);
                     using var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false);
-                    await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                    await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
 
 
                     await _providerManager.SaveImage(
                     await _providerManager.SaveImage(
                         item,
                         item,
@@ -586,7 +586,7 @@ namespace MediaBrowser.Providers.Manager
                         }
                         }
                     }
                     }
 
 
-                    await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                    await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                     await _providerManager.SaveImage(
                     await _providerManager.SaveImage(
                         item,
                         item,
                         stream,
                         stream,

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

@@ -181,7 +181,7 @@ namespace MediaBrowser.Providers.Manager
                 throw new HttpRequestException("Invalid image received.", null, HttpStatusCode.NotFound);
                 throw new HttpRequestException("Invalid image received.", null, HttpStatusCode.NotFound);
             }
             }
 
 
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             await SaveImage(
             await SaveImage(
                 item,
                 item,
                 stream,
                 stream,

+ 1 - 1
MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs

@@ -175,7 +175,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
             Directory.CreateDirectory(Path.GetDirectoryName(path));
             Directory.CreateDirectory(Path.GetDirectoryName(path));
 
 
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
             await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
             await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
             await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
         }
         }

+ 1 - 1
MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs

@@ -156,7 +156,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
             var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
             var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId);
 
 
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
             using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
 
 
             Directory.CreateDirectory(Path.GetDirectoryName(path));
             Directory.CreateDirectory(Path.GetDirectoryName(path));
 
 

+ 3 - 3
MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs

@@ -38,7 +38,7 @@ namespace MediaBrowser.Providers.Music
                 var url = "/ws/2/artist/?query=arid:{0}" + musicBrainzId.ToString(CultureInfo.InvariantCulture);
                 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 response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-                await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                 return GetResultsFromResponse(stream);
                 return GetResultsFromResponse(stream);
             }
             }
             else
             else
@@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Music
                 var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
                 var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
 
 
                 using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
                 using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
-                await using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
+                await using (var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false))
                 {
                 {
                     var results = GetResultsFromResponse(stream).ToList();
                     var results = GetResultsFromResponse(stream).ToList();
 
 
@@ -65,7 +65,7 @@ namespace MediaBrowser.Providers.Music
                     url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
                     url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
 
 
                     using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
                     using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-                    await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                    await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                     return GetResultsFromResponse(stream);
                     return GetResultsFromResponse(stream);
                 }
                 }
             }
             }

+ 5 - 5
MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs

@@ -125,7 +125,7 @@ namespace MediaBrowser.Providers.Music
             if (!string.IsNullOrWhiteSpace(url))
             if (!string.IsNullOrWhiteSpace(url))
             {
             {
                 using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
                 using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-                await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+                await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                 return GetResultsFromResponse(stream);
                 return GetResultsFromResponse(stream);
             }
             }
 
 
@@ -284,7 +284,7 @@ namespace MediaBrowser.Providers.Music
                 artistId);
                 artistId);
 
 
             using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
             using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             using var oReader = new StreamReader(stream, Encoding.UTF8);
             using var oReader = new StreamReader(stream, Encoding.UTF8);
             var settings = new XmlReaderSettings
             var settings = new XmlReaderSettings
             {
             {
@@ -307,7 +307,7 @@ namespace MediaBrowser.Providers.Music
                 WebUtility.UrlEncode(artistName));
                 WebUtility.UrlEncode(artistName));
 
 
             using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
             using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             using var oReader = new StreamReader(stream, Encoding.UTF8);
             using var oReader = new StreamReader(stream, Encoding.UTF8);
             var settings = new XmlReaderSettings()
             var settings = new XmlReaderSettings()
             {
             {
@@ -622,7 +622,7 @@ namespace MediaBrowser.Providers.Music
             var url = "/ws/2/release?release-group=" + releaseGroupId.ToString(CultureInfo.InvariantCulture);
             var url = "/ws/2/release?release-group=" + releaseGroupId.ToString(CultureInfo.InvariantCulture);
 
 
             using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
             using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             using var oReader = new StreamReader(stream, Encoding.UTF8);
             using var oReader = new StreamReader(stream, Encoding.UTF8);
             var settings = new XmlReaderSettings
             var settings = new XmlReaderSettings
             {
             {
@@ -649,7 +649,7 @@ namespace MediaBrowser.Providers.Music
             var url = "/ws/2/release-group/?query=reid:" + releaseEntryId.ToString(CultureInfo.InvariantCulture);
             var url = "/ws/2/release-group/?query=reid:" + releaseEntryId.ToString(CultureInfo.InvariantCulture);
 
 
             using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
             using var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             using var oReader = new StreamReader(stream, Encoding.UTF8);
             using var oReader = new StreamReader(stream, Encoding.UTF8);
             var settings = new XmlReaderSettings
             var settings = new XmlReaderSettings
             {
             {

+ 1 - 1
MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs

@@ -133,7 +133,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
             var url = OmdbProvider.GetOmdbUrl(urlQuery);
             var url = OmdbProvider.GetOmdbUrl(urlQuery);
 
 
             using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
             using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             var resultList = new List<SearchResult>();
             var resultList = new List<SearchResult>();
 
 
             if (isSearch)
             if (isSearch)

+ 2 - 2
MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs

@@ -298,7 +298,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                     imdbParam));
                     imdbParam));
 
 
             using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
             using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false);
             var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<RootObject>(stream).ConfigureAwait(false);
             Directory.CreateDirectory(Path.GetDirectoryName(path));
             Directory.CreateDirectory(Path.GetDirectoryName(path));
             _jsonSerializer.SerializeToFile(rootObject, path);
             _jsonSerializer.SerializeToFile(rootObject, path);
@@ -336,7 +336,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
                     seasonId));
                     seasonId));
 
 
             using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
             using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
-            await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
+            await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
             var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false);
             var rootObject = await _jsonSerializer.DeserializeFromStreamAsync<SeasonRootObject>(stream).ConfigureAwait(false);
             Directory.CreateDirectory(Path.GetDirectoryName(path));
             Directory.CreateDirectory(Path.GetDirectoryName(path));
             _jsonSerializer.SerializeToFile(rootObject, path);
             _jsonSerializer.SerializeToFile(rootObject, path);