diff --git a/src/ReC.Client/ReCClientHelpers.cs b/src/ReC.Client/ReCClientHelpers.cs index 0102710..44bc252 100644 --- a/src/ReC.Client/ReCClientHelpers.cs +++ b/src/ReC.Client/ReCClientHelpers.cs @@ -1,11 +1,10 @@ using System; using System.Globalization; using System.Linq; -using System.Net.Http.Json; - -#if NETFRAMEWORK using System.Net.Http; -#endif +using System.Net.Http.Json; +using System.Threading; +using System.Threading.Tasks; namespace ReC.Client { @@ -45,5 +44,47 @@ namespace ReC.Client /// The payload to serialize. /// A instance ready for HTTP requests. public static JsonContent ToJsonContent(T payload) => JsonContent.Create(payload); + + /// + /// Throws a if the response indicates a non-success status code. + /// + /// The HTTP response to inspect. + /// A token to cancel the operation. + public static async Task EnsureSuccessAsync(HttpResponseMessage response, CancellationToken cancel = default) + { + if (response.IsSuccessStatusCode) + return; + +#if NETFRAMEWORK + string body = null; +#else + string? body = null; +#endif + if (response.Content != null) + { + try + { +#if NETFRAMEWORK + body = await response.Content.ReadAsStringAsync().ConfigureAwait(false); +#else + body = await response.Content.ReadAsStringAsync(cancel).ConfigureAwait(false); +#endif + } + catch + { + // Swallow body read failures; status info is still propagated. + } + } + + var request = response.RequestMessage; + var method = request?.Method?.Method; + var uri = request?.RequestUri; + + var message = $"ReC API request failed with status {(int)response.StatusCode} ({response.ReasonPhrase}). " + + $"{method} {uri}" + + (string.IsNullOrWhiteSpace(body) ? string.Empty : $": {body}"); + + throw new ReCApiException(message, response.StatusCode, response.ReasonPhrase, body, method, uri); + } } }