< Summary

Information
Class: ArturRios.Util.Http.HttpGateway
Assembly: ArturRios.Util
File(s): /home/runner/work/dotnet-util/dotnet-util/src/Http/HttpGateway.cs
Line coverage
100%
Covered lines: 13
Uncovered lines: 0
Coverable lines: 13
Total lines: 105
Line coverage: 100%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage
100%
Covered methods: 9
Fully covered methods: 9
Total methods: 9
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%22100%
get_Client()100%11100%
GetAsync(...)100%11100%
PatchAsync(...)100%11100%
PostAsync(...)100%11100%
PutAsync(...)100%11100%
DeleteAsync(...)100%11100%
Serialize(...)100%22100%
SendAsync()100%11100%

File(s)

/home/runner/work/dotnet-util/dotnet-util/src/Http/HttpGateway.cs

#LineLine coverage
 1namespace ArturRios.Util.Http;
 2
 3/// <summary>
 4/// A lightweight HTTP gateway that wraps <see cref="HttpClient"/> and provides typed helpers
 5/// for common HTTP verbs, returning <see cref="HttpOutput{TBody}"/> with deserialized content.
 6/// </summary>
 7/// <remarks>
 8/// The response body is fully buffered into the returned <see cref="HttpOutput{TBody}"/> and the
 9/// underlying <see cref="HttpResponseMessage"/> is disposed before the call returns, so no connection is
 10/// left pinned by a caller that ignores the result.
 11/// </remarks>
 12/// <param name="client">The client used to perform HTTP requests.</param>
 13/// <exception cref="ArgumentNullException"><paramref name="client"/> is <c>null</c>.</exception>
 2414public class HttpGateway(HttpClient client)
 15{
 16    /// <summary>
 17    /// Gets the underlying <see cref="HttpClient"/> used to perform HTTP requests.
 18    /// </summary>
 5019    public HttpClient Client { get; } = client ?? throw new ArgumentNullException(nameof(client));
 20
 21    /// <summary>
 22    /// Sends a GET request to the specified route and deserializes the response body.
 23    /// </summary>
 24    /// <typeparam name="TBody">The expected response body type.</typeparam>
 25    /// <param name="route">The relative or absolute route for the request.</param>
 26    /// <param name="cancellationToken">Cancels the request and the body read.</param>
 27    /// <returns>An <see cref="HttpOutput{TBody}"/> containing status, headers, and the deserialized body.</returns>
 28    public Task<HttpOutput<TBody?>> GetAsync<TBody>(string route, CancellationToken cancellationToken = default) =>
 3029        SendAsync<TBody>(() => Client.GetAsync(route, cancellationToken), cancellationToken);
 30
 31    /// <summary>
 32    /// Sends a PATCH request with an optional payload, serialized as JSON.
 33    /// </summary>
 34    /// <typeparam name="TBody">The expected response body type.</typeparam>
 35    /// <param name="route">The route to send the request to.</param>
 36    /// <param name="payloadObject">An optional object to be serialized as JSON for the request body.</param>
 37    /// <param name="cancellationToken">Cancels the request and the body read.</param>
 38    /// <returns>An <see cref="HttpOutput{TBody}"/> with the response information and body.</returns>
 39    public Task<HttpOutput<TBody?>> PatchAsync<TBody>(
 40        string route,
 41        object? payloadObject = null,
 42        CancellationToken cancellationToken = default) =>
 443        SendAsync<TBody>(() => Client.PatchAsync(route, Serialize(payloadObject), cancellationToken), cancellationToken)
 44
 45    /// <summary>
 46    /// Sends a POST request with an optional payload, serialized as JSON.
 47    /// </summary>
 48    /// <typeparam name="TBody">The expected response body type.</typeparam>
 49    /// <param name="route">The route to send the request to.</param>
 50    /// <param name="payloadObject">An optional object to be serialized as JSON for the request body.</param>
 51    /// <param name="cancellationToken">Cancels the request and the body read.</param>
 52    /// <returns>An <see cref="HttpOutput{TBody}"/> with the response information and body.</returns>
 53    public Task<HttpOutput<TBody?>> PostAsync<TBody>(
 54        string route,
 55        object? payloadObject = null,
 56        CancellationToken cancellationToken = default) =>
 857        SendAsync<TBody>(() => Client.PostAsync(route, Serialize(payloadObject), cancellationToken), cancellationToken);
 58
 59    /// <summary>
 60    /// Sends a PUT request with an optional payload, serialized as JSON.
 61    /// </summary>
 62    /// <typeparam name="TBody">The expected response body type.</typeparam>
 63    /// <param name="route">The route to send the request to.</param>
 64    /// <param name="payloadObject">An optional object to be serialized as JSON for the request body.</param>
 65    /// <param name="cancellationToken">Cancels the request and the body read.</param>
 66    /// <returns>An <see cref="HttpOutput{TBody}"/> with the response information and body.</returns>
 67    public Task<HttpOutput<TBody?>> PutAsync<TBody>(
 68        string route,
 69        object? payloadObject = null,
 70        CancellationToken cancellationToken = default) =>
 471        SendAsync<TBody>(() => Client.PutAsync(route, Serialize(payloadObject), cancellationToken), cancellationToken);
 72
 73    /// <summary>
 74    /// Sends a DELETE request to the specified route and deserializes the response body.
 75    /// </summary>
 76    /// <typeparam name="TBody">The expected response body type.</typeparam>
 77    /// <param name="route">The route to send the request to.</param>
 78    /// <param name="cancellationToken">Cancels the request and the body read.</param>
 79    /// <returns>An <see cref="HttpOutput{TBody}"/> with the response information and body.</returns>
 80    public Task<HttpOutput<TBody?>> DeleteAsync<TBody>(string route, CancellationToken cancellationToken = default) =>
 481        SendAsync<TBody>(() => Client.DeleteAsync(route, cancellationToken), cancellationToken);
 82
 83    /// <summary>
 84    /// Serializes an optional payload, leaving a null payload as no request body at all rather than the
 85    /// JSON literal <c>null</c>.
 86    /// </summary>
 887    private static HttpContent? Serialize(object? payloadObject) => payloadObject?.ToJsonStringContent();
 88
 89    /// <summary>
 90    /// Runs a request, buffers the response into an <see cref="HttpOutput{TBody}"/> and disposes the
 91    /// response message.
 92    /// </summary>
 93    private static async Task<HttpOutput<TBody?>> SendAsync<TBody>(
 94        Func<Task<HttpResponseMessage>> send,
 95        CancellationToken cancellationToken)
 96    {
 2597        using var response = await send().ConfigureAwait(false);
 98
 2299        var output = new HttpOutput<TBody?>(response);
 100
 22101        await output.ReadContentAsync(cancellationToken).ConfigureAwait(false);
 102
 22103        return output;
 22104    }
 105}