tgstation-server 6.12.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
RequestFileStreamProvider.cs
Go to the documentation of this file.
1using System;
2using System.IO;
3using System.Net.Http;
4using System.Threading;
5using System.Threading.Tasks;
6
8
10{
15 {
20
24 readonly HttpRequestMessage requestMessage;
25
29 readonly CancellationTokenSource downloadCts;
30
34 Task<CachedResponseStream>? downloadTask;
35
39 volatile bool disposed;
40
47 {
48 this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
49 this.requestMessage = requestMessage ?? throw new ArgumentNullException(nameof(requestMessage));
50
51 downloadCts = new CancellationTokenSource();
52 }
53
55 public async ValueTask DisposeAsync()
56 {
57 Task<CachedResponseStream>? localDownloadTask;
58 lock (downloadCts)
59 {
60 if (disposed)
61 return;
62
63 disposed = true;
64
65 localDownloadTask = downloadTask;
66 downloadTask = null;
67 }
68
69 downloadCts.Cancel();
70 downloadCts.Dispose();
71
72 if (localDownloadTask != null)
73 {
75 try
76 {
77 result = await localDownloadTask;
78 }
79 catch
80 {
81 // Unsightly yes, but, if we're here, that means someone called GetResult. So, either they handled the error or decided to ignore it
82 return;
83 }
84
85 await result.DisposeAsync();
86 }
87
89 httpClient.Dispose();
90 }
91
93 public async ValueTask<Stream> GetResult(CancellationToken cancellationToken)
94 {
95 if (disposed)
96 throw new ObjectDisposedException(nameof(RequestFileStreamProvider));
97
98 Task<CachedResponseStream> localTask;
99 using (cancellationToken.Register(() => downloadCts.Cancel()))
100 {
101 lock (downloadCts)
102 {
104 localTask = downloadTask;
105 }
106
107 return await localTask;
108 }
109 }
110
116 async Task<CachedResponseStream> InitiateDownload(CancellationToken cancellationToken)
117 {
118 var response = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
119 try
120 {
121 response.EnsureSuccessStatusCode();
122 return await CachedResponseStream.Create(response);
123 }
124 catch
125 {
126 response.Dispose();
127 throw;
128 }
129 }
130 }
131}
Caches the Stream from a HttpResponseMessage for later use.
static async ValueTask< CachedResponseStream > Create(HttpResponseMessage response)
Asyncronously creates a new CachedResponseStream.
A IFileStreamProvider that represents the response of HttpRequestMessages.
volatile bool disposed
If DisposeAsync has been called.
Task< CachedResponseStream >? downloadTask
The Task<TResult> resulting in the downloaded MemoryStream.
readonly IHttpClient httpClient
The IHttpClient for the RequestFileStreamProvider.
readonly CancellationTokenSource downloadCts
The CancellationTokenSource used to abort the download.
async Task< CachedResponseStream > InitiateDownload(CancellationToken cancellationToken)
Initiate the download.
readonly HttpRequestMessage requestMessage
The IFileDownloader for the RequestFileStreamProvider.
RequestFileStreamProvider(IHttpClient httpClient, HttpRequestMessage requestMessage)
Initializes a new instance of the RequestFileStreamProvider class.
async ValueTask< Stream > GetResult(CancellationToken cancellationToken)
Gets the provided Stream. May be called multiple times, though cancelling any may cause all calls to ...
Task< HttpResponseMessage > SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
Send an HTTP request.
Interface for asynchronously consuming Streams of files.