2020-12-28 14:34:13 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
2023-05-15 15:16:12 -04:00
|
|
|
using System;
|
2020-12-28 14:34:13 -04:00
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.Json;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
2022-10-03 17:01:13 -04:00
|
|
|
#pragma warning disable CA2234 // Pass system uri objects instead of strings
|
|
|
|
|
#pragma warning disable CA1054 // URI-like parameters should not be strings
|
|
|
|
|
|
2020-12-28 14:34:13 -04:00
|
|
|
namespace EpicGames.Core
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Extension methods for consuming REST APIs via JSON objects
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static class HttpClientExtensions
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a resource from an HTTP endpoint and parses it as a JSON object
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="TResponse">The object type to return</typeparam>
|
2022-03-24 16:35:00 -04:00
|
|
|
/// <param name="client">The http client instance</param>
|
|
|
|
|
/// <param name="url">The url to retrieve</param>
|
|
|
|
|
/// <param name="cancellationToken">Cancels the request</param>
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <returns>New instance of the object</returns>
|
2023-05-17 14:14:48 -04:00
|
|
|
public static async Task<TResponse> GetAsync<TResponse>(this HttpClient client, string url, CancellationToken cancellationToken)
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2022-03-24 16:35:00 -04:00
|
|
|
using (HttpResponseMessage response = await client.GetAsync(url, cancellationToken))
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2022-03-24 16:35:00 -04:00
|
|
|
response.EnsureSuccessStatusCode();
|
2023-09-16 12:23:02 -04:00
|
|
|
return await ParseJsonContentAsync<TResponse>(response, cancellationToken);
|
2020-12-28 14:34:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-17 14:14:48 -04:00
|
|
|
/// <inheritdoc cref="GetAsync{TResponse}(HttpClient, String, CancellationToken)"/>
|
|
|
|
|
public static async Task<TResponse> GetAsync<TResponse>(this HttpClient client, Uri url, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
using (HttpResponseMessage response = await client.GetAsync(url, cancellationToken))
|
|
|
|
|
{
|
|
|
|
|
response.EnsureSuccessStatusCode();
|
2023-09-16 12:23:02 -04:00
|
|
|
return await ParseJsonContentAsync<TResponse>(response, cancellationToken);
|
2023-05-17 14:14:48 -04:00
|
|
|
}
|
|
|
|
|
}
|
2023-05-15 15:16:12 -04:00
|
|
|
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <summary>
|
|
|
|
|
/// Posts an object to an HTTP endpoint as a JSON object
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="TRequest">The object type to post</typeparam>
|
2022-03-24 16:35:00 -04:00
|
|
|
/// <param name="client">The http client instance</param>
|
|
|
|
|
/// <param name="url">The url to post to</param>
|
|
|
|
|
/// <param name="request">The object to post</param>
|
|
|
|
|
/// <param name="cancellationToken">Cancels the request</param>
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <returns>Response message</returns>
|
2023-05-17 14:14:48 -04:00
|
|
|
public static async Task<HttpResponseMessage> PostAsync<TRequest>(this HttpClient client, string url, TRequest request, CancellationToken cancellationToken)
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2022-10-03 17:01:13 -04:00
|
|
|
using HttpContent content = ToJsonContent(request);
|
|
|
|
|
return await client.PostAsync(url, content, cancellationToken);
|
2020-12-28 14:34:13 -04:00
|
|
|
}
|
|
|
|
|
|
2023-05-17 14:14:48 -04:00
|
|
|
/// <inheritdoc cref="PostAsync{TRequest}(HttpClient, String, TRequest, CancellationToken)"/>
|
|
|
|
|
public static async Task<HttpResponseMessage> PostAsync<TRequest>(this HttpClient client, Uri url, TRequest request, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
using HttpContent content = ToJsonContent(request);
|
|
|
|
|
return await client.PostAsync(url, content, cancellationToken);
|
|
|
|
|
}
|
2023-05-15 15:16:12 -04:00
|
|
|
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <summary>
|
|
|
|
|
/// Posts an object to an HTTP endpoint as a JSON object, and parses the response object
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="TResponse">The object type to return</typeparam>
|
|
|
|
|
/// <typeparam name="TRequest">The object type to post</typeparam>
|
2022-03-24 16:35:00 -04:00
|
|
|
/// <param name="client">The http client instance</param>
|
|
|
|
|
/// <param name="url">The url to post to</param>
|
|
|
|
|
/// <param name="request">The object to post</param>
|
|
|
|
|
/// <param name="cancellationToken">Cancels the request</param>
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <returns>The response parsed into the requested type</returns>
|
2023-05-17 14:14:48 -04:00
|
|
|
public static async Task<TResponse> PostAsync<TResponse, TRequest>(this HttpClient client, string url, TRequest request, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
using (HttpResponseMessage response = await PostAsync(client, url, request, cancellationToken))
|
|
|
|
|
{
|
|
|
|
|
response.EnsureSuccessStatusCode();
|
2023-09-16 12:23:02 -04:00
|
|
|
return await ParseJsonContentAsync<TResponse>(response, cancellationToken);
|
2023-05-17 14:14:48 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc cref="PostAsync{TRequest}(HttpClient, String, TRequest, CancellationToken)"/>
|
2023-05-15 15:16:12 -04:00
|
|
|
public static async Task<TResponse> PostAsync<TResponse, TRequest>(this HttpClient client, Uri url, TRequest request, CancellationToken cancellationToken)
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2022-03-24 16:35:00 -04:00
|
|
|
using (HttpResponseMessage response = await PostAsync(client, url, request, cancellationToken))
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2022-03-24 16:35:00 -04:00
|
|
|
response.EnsureSuccessStatusCode();
|
2023-09-16 12:23:02 -04:00
|
|
|
return await ParseJsonContentAsync<TResponse>(response, cancellationToken);
|
2020-12-28 14:34:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Puts an object to an HTTP endpoint as a JSON object
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="TRequest">The object type to post</typeparam>
|
2022-03-24 16:35:00 -04:00
|
|
|
/// <param name="client">The http client instance</param>
|
|
|
|
|
/// <param name="url">The url to post to</param>
|
2023-05-17 14:14:48 -04:00
|
|
|
/// <param name="request">The object to post</param>
|
2022-03-24 16:35:00 -04:00
|
|
|
/// <param name="cancellationToken">Cancels the request</param>
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <returns>Response message</returns>
|
2023-05-17 14:14:48 -04:00
|
|
|
public static async Task<HttpResponseMessage> PutAsync<TRequest>(this HttpClient client, string url, TRequest request, CancellationToken cancellationToken)
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2023-05-17 14:14:48 -04:00
|
|
|
using HttpContent content = ToJsonContent(request);
|
2022-10-03 17:01:13 -04:00
|
|
|
return await client.PutAsync(url, content, cancellationToken);
|
2020-12-28 14:34:13 -04:00
|
|
|
}
|
|
|
|
|
|
2023-05-17 14:14:48 -04:00
|
|
|
/// <inheritdoc cref="PutAsync{TRequest}(HttpClient, String, TRequest, CancellationToken)"/>
|
|
|
|
|
public static async Task<HttpResponseMessage> PutAsync<TRequest>(this HttpClient client, Uri url, TRequest request, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
using HttpContent content = ToJsonContent(request);
|
|
|
|
|
return await client.PutAsync(url, content, cancellationToken);
|
|
|
|
|
}
|
2023-05-15 15:16:12 -04:00
|
|
|
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <summary>
|
|
|
|
|
/// Puts an object to an HTTP endpoint as a JSON object, and parses the response object
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="TResponse">The object type to return</typeparam>
|
|
|
|
|
/// <typeparam name="TRequest">The object type to post</typeparam>
|
2022-03-24 16:35:00 -04:00
|
|
|
/// <param name="client">The http client instance</param>
|
|
|
|
|
/// <param name="url">The url to post to</param>
|
|
|
|
|
/// <param name="request">The object to post</param>
|
|
|
|
|
/// <param name="cancellationToken">Cancels the request</param>
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <returns>The response parsed into the requested type</returns>
|
2023-05-17 14:14:48 -04:00
|
|
|
public static async Task<TResponse> PutAsync<TResponse, TRequest>(this HttpClient client, string url, TRequest request, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
using (HttpResponseMessage response = await PutAsync(client, url, request, cancellationToken))
|
|
|
|
|
{
|
|
|
|
|
response.EnsureSuccessStatusCode();
|
2023-09-16 12:23:02 -04:00
|
|
|
return await ParseJsonContentAsync<TResponse>(response, cancellationToken);
|
2023-05-17 14:14:48 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc cref="PutAsync{TRequest}(HttpClient, String, TRequest, CancellationToken)"/>
|
2023-05-15 15:16:12 -04:00
|
|
|
public static async Task<TResponse> PutAsync<TResponse, TRequest>(this HttpClient client, Uri url, TRequest request, CancellationToken cancellationToken)
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2022-03-24 16:35:00 -04:00
|
|
|
using (HttpResponseMessage response = await PutAsync(client, url, request, cancellationToken))
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2022-03-24 16:35:00 -04:00
|
|
|
response.EnsureSuccessStatusCode();
|
2023-09-16 12:23:02 -04:00
|
|
|
return await ParseJsonContentAsync<TResponse>(response, cancellationToken);
|
2020-12-28 14:34:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Converts an object to a JSON http content object
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="T">Type of the object to parse</typeparam>
|
2022-03-24 16:35:00 -04:00
|
|
|
/// <param name="obj">The object instance</param>
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <returns>Http content object</returns>
|
2022-03-24 16:35:00 -04:00
|
|
|
private static HttpContent ToJsonContent<T>(T obj)
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2022-03-24 16:35:00 -04:00
|
|
|
return new StringContent(JsonSerializer.Serialize<T>(obj), Encoding.UTF8, "application/json");
|
2020-12-28 14:34:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a HTTP response as a JSON object
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="T">Type of the object to parse</typeparam>
|
2022-03-24 16:35:00 -04:00
|
|
|
/// <param name="message">The message received</param>
|
2023-06-14 22:18:34 -04:00
|
|
|
/// <param name="cancellationToken">Cancellation token for the operation</param>
|
2020-12-28 14:34:13 -04:00
|
|
|
/// <returns>Parsed object instance</returns>
|
2023-09-16 12:23:02 -04:00
|
|
|
private static async Task<T> ParseJsonContentAsync<T>(HttpResponseMessage message, CancellationToken cancellationToken)
|
2020-12-28 14:34:13 -04:00
|
|
|
{
|
2023-06-14 22:18:34 -04:00
|
|
|
byte[] bytes = await message.Content.ReadAsByteArrayAsync(cancellationToken);
|
2022-09-30 13:49:15 -04:00
|
|
|
return JsonSerializer.Deserialize<T>(bytes, new JsonSerializerOptions { PropertyNameCaseInsensitive = true })!;
|
2020-12-28 14:34:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|