using System; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Http.Json; using System.Threading; using System.Threading.Tasks; namespace Sandbox; public static partial class Http { /// /// Send a HTTP request to the specified URI and return the response body as a string in an asynchronous operation. /// /// The URI to request. /// The HTTP verb for the request (eg. GET, POST, etc.). /// The content to include within the request, or null if none should be sent. /// Headers to add to the request, or null if none should be added. /// An optional cancellation token for canceling this request. /// An asynchronous task which resolves to the response body as a string. /// The request responded with a non-2xx HTTP status code. /// The request was not allowed, either an unallowed URI or header. public static async Task RequestStringAsync( string requestUri, string method = "GET", HttpContent content = null, Dictionary headers = null, CancellationToken cancellationToken = default ) { using var response = await RequestAsync( requestUri, method, content, headers: headers, cancellationToken: cancellationToken ); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStringAsync( cancellationToken ); } /// /// Send a HTTP request to the specified URI and return the response body as a byte array in an asynchronous operation. /// /// The URI to request. /// The HTTP verb for the request (eg. GET, POST, etc.). /// The content to include within the request, or null if none should be sent. /// Headers to add to the request, or null if none should be added. /// An optional cancellation token for canceling this request. /// An asynchronous task which resolves to the response body as a byte array. /// The request responded with a non-2xx HTTP status code. /// The request was not allowed, either an unallowed URI or header. public static async Task RequestBytesAsync( string requestUri, string method = "GET", HttpContent content = null, Dictionary headers = null, CancellationToken cancellationToken = default ) { using var response = await RequestAsync( requestUri, method, content, headers: headers, cancellationToken: cancellationToken ); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsByteArrayAsync( cancellationToken ); } /// /// Send a HTTP request to the specified URI and return the response body as a stream in an asynchronous operation. /// /// The URI to request. /// The HTTP verb for the request (eg. GET, POST, etc.). /// The content to include within the request, or null if none should be sent. /// Headers to add to the request, or null if none should be added. /// An optional cancellation token for canceling this request. /// An asynchronous task which resolves to the response body as a . /// The request responded with a non-2xx HTTP status code. /// The request was not allowed, either an unallowed URI or header. public static async Task RequestStreamAsync( string requestUri, string method = "GET", HttpContent content = null, Dictionary headers = null, CancellationToken cancellationToken = default ) { using var response = await RequestAsync( requestUri, method, content, headers: headers, cancellationToken: cancellationToken ); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsStreamAsync( cancellationToken ); } /// /// Sends a HTTP request to the specified URI and return the response body as a JSON deserialized object in an asynchronous operation. /// /// The URI to request. /// The HTTP verb for the request (eg. GET, POST, etc.). /// The content to include within the request, or null if none should be sent. /// Headers to add to the request, or null if none should be added. /// An optional cancellation token for canceling this request. /// An asynchronous task which resolves to the response body deserialized from JSON. /// The request responded with a non-2xx HTTP status code. /// The request was not allowed, either an unallowed URI or header. public static async Task RequestJsonAsync( string requestUri, string method = "GET", HttpContent content = null, Dictionary headers = null, CancellationToken cancellationToken = default ) { using var response = await RequestAsync( requestUri, method, content, headers: headers, cancellationToken: cancellationToken ); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync( cancellationToken: cancellationToken ); } /// /// Sends a HTTP request to the specified URI and returns the response in an asynchronous operation. /// /// The URI to request. /// The HTTP verb for the request (eg. GET, POST, etc.). /// The content to include within the request, or null if none should be sent. /// Headers to add to the request, or null if none should be added. /// An optional cancellation token for canceling this request. /// An asynchronous task which resolves to a containing the response for the request. /// The request responded with a non-2xx HTTP status code. /// The request was not allowed, either an unallowed URI or header. public static async Task RequestAsync( string requestUri, string method = "GET", HttpContent content = null, Dictionary headers = null, CancellationToken cancellationToken = default ) { if ( string.IsNullOrWhiteSpace( method ) ) { throw new ArgumentNullException( nameof( method ) ); } using var request = CreateRequest( new HttpMethod( method ), requestUri, headers ); request.Content = content; return await Client.SendAsync( request, cancellationToken ); } /// /// Creates a new instance containing the specified object serialized to JSON. /// public static HttpContent CreateJsonContent( T target ) { return JsonContent.Create( target, new MediaTypeHeaderValue( "application/json" ) ); } internal static HttpRequestMessage CreateRequest( HttpMethod method, string requestUri, Dictionary headers ) { var uri = new Uri( requestUri, UriKind.Absolute ); if ( !IsAllowed( uri ) ) { throw new InvalidOperationException( $"Access to '{uri}' is not allowed." ); } var request = new HttpRequestMessage( method, uri ); if ( headers != null ) { foreach ( var (key, value) in headers ) { if ( !IsHeaderAllowed( key ) ) { throw new InvalidOperationException( $"Not allowed to set header '{key}'." ); } request.Headers.TryAddWithoutValidation( key, value ); } } return request; } }