Class HttpRestClient
- Namespace
- Kampute.HttpClient
- Assembly
- Kampute.HttpClient.dll
Facilitates HTTP communication with RESTful APIs by wrapping HttpClient.
public class HttpRestClient : IDisposable
- Inheritance
-
HttpRestClient
- Implements
- Inherited Members
- Extension Methods
Remarks
HttpRestClient abstracts the complexities of HttpClient, supporting the sharing of a single HttpClient instance across multiple HttpRestClient instances. This optimizes resource use and connection management, enhancing performance by reusing HTTP connections, especially during concurrent access to various services or API endpoints.
The client allows for scoped request headers and properties, providing temporary configurations that do not alter global settings. This ensures that changes remain isolated to specific contexts, increasing maintainability and reducing configuration errors during runtime.
It includes a ResponseDeserializers collection that automatically deserializes HTTP response content into .NET objects based on the
response's Content-Type
. If the Accept
header is not predefined, the client dynamically adjusts it based on the configured response
deserializers and the expected .NET object type.
Transient failures and network interruptions are managed via the BackoffStrategy property, which outlines retry logic and wait times between retries. This strategic approach helps avoid server overloads and improves communication success without excessive resource use.
Extensible error handling is enabled through the ErrorHandlers collection, allowing custom IHttpErrorHandler implementations to handle specific HTTP errors with tailored strategies.
Lifecycle events like BeforeSendingRequest and AfterReceivingResponse enhance request and response handling by enabling modifications, inspections, and logging, allowing for a highly customizable interaction.
Constructors
HttpRestClient()
Initializes a new instance of the HttpRestClient class.
public HttpRestClient()
Remarks
This constructor initializes the HttpRestClient using a shared HttpClient instance acquired from the SharedHttpClient static class.
HttpRestClient(Reference)
Initializes a new instance of the HttpRestClient class with the specified shared HttpClient reference.
public HttpRestClient(SharedDisposable<HttpClient>.Reference httpClientReference)
Parameters
httpClientReference
SharedDisposable<HttpClient>.ReferenceA reference to a shared HttpClient instance, managed as SharedDisposable<T>.Reference.
Remarks
This constructor takes ownership of the shared HttpClient reference and ensures it is properly released when the HttpRestClient is disposed.
Exceptions
- ArgumentNullException
Thrown if
httpClientReference
is null>.
HttpRestClient(HttpClient, bool)
Initializes a new instance of the HttpRestClient class with the specified HttpClient.
public HttpRestClient(HttpClient httpClient, bool disposeClient = true)
Parameters
httpClient
HttpClientThe HttpClient to be used by the HttpRestClient.
disposeClient
boolSpecifies whether the HttpRestClient should dispose of the provided HttpClient when the HttpRestClient is disposed.
Exceptions
- ArgumentNullException
Thrown if
httpClient
is null.
Properties
BackoffStrategy
Gets or sets the backoff strategy for handling transient connection failures during HTTP requests.
public IHttpBackoffProvider BackoffStrategy { get; set; }
Property Value
- IHttpBackoffProvider
The backoff strategy for handling transient connection failures during HTTP requests.
Remarks
This property specifies the retry logic applied exclusively to connection failures, not to the processing of server responses. It determines if and when the client should retry a failed connection attempt before giving up. This approach is crucial for dealing with transient network issues or temporary server unavailability. The default is None.
BaseAddress
Gets or sets the base address for HTTP requests.
public Uri? BaseAddress { get; set; }
Property Value
- Uri
The base address for HTTP requests.
Remarks
If the provided base address does not end with a slash, one is automatically appended. The presence or absence of this trailing slash is significant in how relative URLs are resolved. For instance, if the base address is http://example.com/api (no trailing slash) and the relative URL is "users", the resolved URL will be http://example.com/users. Conversely, if the base address ends with a slash, like http://example.com/api/, the resolved URL will be http://example.com/api/users. This subtle difference can be crucial in ensuring requests are routed correctly.
It's also worth noting that a null value for the base address is acceptable and indicates that no base address is set. In such cases, any HTTP request must use an absolute URL.
DefaultRequestHeaders
Gets the headers which should be sent with each request.
public HttpRequestHeaders DefaultRequestHeaders { get; }
Property Value
- HttpRequestHeaders
The headers which should be sent with each request.
ErrorHandlers
Gets the mutable collection of HTTP error handlers used for handling error responses.
public HttpErrorHandlerCollection ErrorHandlers { get; }
Property Value
- HttpErrorHandlerCollection
The mutable collection of HTTP error handlers used for handling error responses.
Remarks
This property provides access to a collection of IHttpErrorHandler instances that are used to handle HTTP error responses. The handlers in this collection are tried in order to handle errors.
ResponseDeserializers
Gets the mutable collection of HTTP content deserializers used for deserializing response content.
public HttpContentDeserializerCollection ResponseDeserializers { get; }
Property Value
- HttpContentDeserializerCollection
The mutable collection of HTTP content deserializers used for deserializing response content.
Remarks
This property provides access to a collection of IHttpContentDeserializer instances that are used to deserialize the content of HTTP responses. The deserializers in this list are tried in order to deserialize the response content into .NET objects.
ResponseErrorType
Gets or sets the Type used to deserialize the response body when the response status code indicates an error.
public Type? ResponseErrorType { get; set; }
Property Value
- Type
The Type used to deserialize the response body when the response status code indicates an error.
Remarks
This property specifies the Type that the HttpRestClient will use to deserialize the response content in cases where the HTTP response indicates an error. It is important to ensure that the custom type specified is compatible with the expected error response format and can be deserialized by the content deserializers available to the HttpRestClient.
When the specified type implements the IHttpErrorResponse interface, the deserialized object is utilized to construct a more informative exception. This mechanism enables the integration of custom error handling strategies by leveraging structured error information returned from the server.
Methods
BeginHeaderScope(IEnumerable<KeyValuePair<string, string?>>)
Begins a new scope with the specified request headers.
public virtual IDisposable BeginHeaderScope(IEnumerable<KeyValuePair<string, string?>> headers)
Parameters
headers
IEnumerable<KeyValuePair<string, string>>The request headers to be applied exclusively during the lifetime of the new scope.
Returns
- IDisposable
An IDisposable representing the new scope. Disposing of this object will end the scope and revert changes in the request headers.
Remarks
This method creates a scope associated with the current HttpRestClient instance to add, modify or remove any request header in subsequent requests during the lifetime of this scope. To remove a header, use null for its value.
Any header modifications made within this scope take precedence over the client's default headers. Header adjustments by other active scopes are overridden by those provided in this scope. However, the default request headers set on the underlying HttpClient instance take precedence over the default and scoped headers of the HttpRestClient instance because they are applied later in the message handler pipeline. To avoid conflicts, it is recommended to keep the default request headers of the underlying HttpClient instance empty.
Upon disposing of the scope, all header adjustments are reverted, restoring the headers to their state before the scope was activated.
Exceptions
- ArgumentNullException
Thrown if
headers
is null.
BeginPropertyScope(IEnumerable<KeyValuePair<string, object?>>)
Begins a new scope with the specified request properties.
public virtual IDisposable BeginPropertyScope(IEnumerable<KeyValuePair<string, object?>> properties)
Parameters
properties
IEnumerable<KeyValuePair<string, object>>The request properties to be applied exclusively during the lifetime of the new scope.
Returns
- IDisposable
An IDisposable representing the new scope. Disposing of this object will end the scope and revert changes in the request properties.
Remarks
This method creates a scope associated with the current HttpRestClient instance to add, modify or remove any request properties in subsequent requests during the lifetime of this scope. To remove a property, use null for its value.
Upon disposing of the scope, all property adjustments are reverted, restoring the properties to their state before the scope was activated.
Exceptions
- ArgumentNullException
Thrown if
properties
is null.
CreateHttpRequest(HttpMethod, string, Type?)
Creates an HttpRequestMessage with the specified method and URI.
protected virtual HttpRequestMessage CreateHttpRequest(HttpMethod method, string uri, Type? responseObjectType)
Parameters
method
HttpMethodThe HTTP method to be used for the request, such as GET, POST, PUT, etc.
uri
stringThe URI to which the request will be sent. Should be a valid, fully qualified URL.
responseObjectType
TypeThe type of the object expected to be contained in the response.
Returns
- HttpRequestMessage
An HttpRequestMessage configured with the specified method and URI.
Remarks
This method constructs a new HTTP request message by setting the HTTP method and URI. It prepares the request for transmission by configuring both the headers and custom properties appropriate for the given context and operation.
Headers are added or adjusted from both the default headers provided by the DefaultRequestHeaders property and any scoped headers that are active at the time of this request’s creation. Scoped headers are prioritized over default headers in case of key conflicts to ensure that context-specific modifications are respected.
If an Accept
header is absent in both default and scoped headers, it is added based on the media types supported by the content deserializers
for the specified responseObjectType
. If responseObjectType
is null, the header defaults to accepting all
media types ("*/*").
This method also includes scoped properties in the HTTP request message to provide additional context and facilitate easier tracking and processing of the request. In addition to the scoped properties, the following properties are added:
- TransactionId A unique identifier (Guid) generated and assigned to each request, aiding in the request's tracking, debugging, and logging processes. The unique identifier ensures that each request can be individually tracked, even when multiple requests are executed simultaneously or when requests are retried due to transient failures.
- ResponseObjectType Defines the .NET type (Type) expected in the response, if any. This metadata provides context that can improve debugging, enhance logging details, and support error recovery strategies.
Exceptions
- ArgumentNullException
Thrown if
method
oruri
is null.
DecideOnRetryAsync(HttpResponseException, HttpRequestMessage, HttpResponseMessage, CancellationToken)
Asynchronously evaluates failed HTTP responses to decide the appropriate action based on the error context and predefined error handling strategies.
protected virtual Task<HttpErrorHandlerResult> DecideOnRetryAsync(HttpResponseException error, HttpRequestMessage request, HttpResponseMessage response, CancellationToken cancellationToken)
Parameters
error
HttpResponseExceptionThe HttpResponseException encapsulating details of the encountered error during the HTTP request execution.
request
HttpRequestMessageThe HttpRequestMessage that led to the failed response.
response
HttpResponseMessageThe received HttpResponseMessage indicating a failure.
cancellationToken
CancellationTokenA token for canceling the operation.
Returns
- Task<HttpErrorHandlerResult>
A task that resolves to an HttpErrorHandlerResult, indicating whether to retry the request or that the error is unrecoverable.
Remarks
This method assesses HTTP request failures, leveraging error handling strategies within ErrorHandlers. It returns an HttpErrorHandlerResult that guides the next steps, either to retry the request with potentially modified parameters or to handle the error as unrecoverable.
Exceptions
- ArgumentNullException
Thrown if
error
,request
orresponse
is null.
- See Also
DecideOnRetryAsync(HttpRequestException, HttpRequestMessage, CancellationToken)
Asynchronously evaluates transient network issues to decide the appropriate action based on the error context and predefined error handling strategies.
protected virtual Task<HttpErrorHandlerResult> DecideOnRetryAsync(HttpRequestException error, HttpRequestMessage request, CancellationToken cancellationToken)
Parameters
error
HttpRequestExceptionThe HttpRequestException encapsulating details of the encountered error during the HTTP request execution.
request
HttpRequestMessageThe HttpRequestMessage that led to the failed response.
cancellationToken
CancellationTokenA token for canceling the operation.
Returns
- Task<HttpErrorHandlerResult>
A task that resolves to an HttpErrorHandlerResult, indicating whether to retry the request or that the error is unrecoverable.
Remarks
This method assesses transient network issues, leveraging backoff strategies specified by BackoffStrategy. It returns an HttpErrorHandlerResult that guides the next steps, either to retry the request with potentially modified parameters or to handle the error as unrecoverable.
Exceptions
- ArgumentNullException
Thrown if
error
orrequest
is null.
- See Also
DeserializeContentAsync(HttpResponseMessage, Type, CancellationToken)
Asynchronously deserializes the body of an HttpResponseMessage and converts it into an object of a specified type.
protected virtual Task<object?> DeserializeContentAsync(HttpResponseMessage response, Type objectType, CancellationToken cancellationToken)
Parameters
response
HttpResponseMessageThe HttpResponseMessage to be read.
objectType
TypeThe type of object to which the response body is to be converted.
cancellationToken
CancellationTokenA token for canceling the operation.
Returns
- Task<object>
A task representing the asynchronous operation, with the deserialized response body as an object.
Remarks
This method uses configured content deserializers for content deserialization and supports custom content types. In case of deserialization failures, an HttpContentException is thrown, which may contain an inner exception providing more details about the parsing error.
Exceptions
- ArgumentNullException
Thrown if
response
orobjectType
is null.- HttpContentException
Thrown when the response body is empty, the content type is unsupported, or parsing the response fails.
- See Also
DispatchAsync(HttpRequestMessage, CancellationToken)
Asynchronously dispatches an HTTP request.
protected virtual Task<HttpResponseMessage> DispatchAsync(HttpRequestMessage request, CancellationToken cancellationToken)
Parameters
request
HttpRequestMessageThe HttpRequestMessage to send.
cancellationToken
CancellationTokenA token for canceling the request.
Returns
- Task<HttpResponseMessage>
A task that represents the asynchronous operation, with a result of the HttpResponseMessage received in response to the request.
Remarks
This method sends the provided HTTP request and returns the response if the status code indicates a success. For any error status codes, it fails fast by throwing an exception specific to the nature of the error. Additionally, the method incorporates pre-send and post-receive hooks for adding custom logic, such as modifying request headers or logging response details.
Exceptions
- HttpResponseException
Thrown if the response status code indicates a failure.
- HttpRequestException
Thrown if the request fails due to an underlying issue such as network connectivity, DNS failure, server certificate validation, or timeout.
- OperationCanceledException
Thrown if the operation is canceled via the cancellation token.
DispatchWithRetriesAsync(HttpRequestMessage, CancellationToken)
Sends an asynchronous HTTP request, with the possibility of retrying the request based on specific failure conditions.
protected virtual Task<HttpResponseMessage> DispatchWithRetriesAsync(HttpRequestMessage request, CancellationToken cancellationToken = default)
Parameters
request
HttpRequestMessageThe HttpRequestMessage to send.
cancellationToken
CancellationTokenA token for canceling the request (optional).
Returns
- Task<HttpResponseMessage>
A task that represents the asynchronous operation, with a result of the HttpResponseMessage received in response to the request.
Remarks
This method is responsible for sending the HTTP request and optionally retrying it under specific failure conditions. The decision to retry a request is based on the nature of the failure, with potential consultation of external retry logic mechanisms.
Exceptions
- ArgumentNullException
Thrown if
request
is null.- HttpResponseException
Thrown if the response status code indicates a failure.
- HttpRequestException
Thrown if the request fails due to an underlying issue such as network connectivity, DNS failure, server certificate validation, or timeout.
- OperationCanceledException
Thrown if the operation is canceled via the cancellation token.
- See Also
Dispose()
Releases the unmanaged resources used by the HttpRestClient and optionally disposes of the managed resources.
public void Dispose()
Dispose(bool)
Disposes the HttpRestClient instance.
protected virtual void Dispose(bool disposing)
Parameters
~HttpRestClient()
Releases unmanaged resources.
protected ~HttpRestClient()
OnAfterReceivingResponse(HttpResponseMessage)
Raises the AfterReceivingResponse event.
protected virtual void OnAfterReceivingResponse(HttpResponseMessage response)
Parameters
response
HttpResponseMessageThe HTTP response message that was received.
Remarks
This method is called to trigger the AfterReceivingResponse event. This allows to react to the reception of an HTTP response. The method is invoked after a response is received from an HTTP request but before any processing is performed on the response.
OnBeforeSendingRequest(HttpRequestMessage)
Raises the BeforeSendingRequest event.
protected virtual void OnBeforeSendingRequest(HttpRequestMessage request)
Parameters
request
HttpRequestMessageThe HTTP request message that was created.
Remarks
This method is called to trigger the BeforeSendingRequest event. This allows for centralized handling of request modifications across various methods that send HTTP requests. The method is invoked before an HttpRequestMessage is sent.
OnDisposing()
Raises the Disposing event.
protected virtual void OnDisposing()
SendAsync(HttpMethod, string, HttpContent?, CancellationToken)
Sends an asynchronous HTTP request with the specified method, URI, and payload, without processing the response body.
public virtual Task<HttpResponseMessage> SendAsync(HttpMethod method, string uri, HttpContent? payload = null, CancellationToken cancellationToken = default)
Parameters
method
HttpMethodThe HTTP method to use for the request.
uri
stringThe URI to which the request is sent.
payload
HttpContentThe HTTP request payload content (optional).
cancellationToken
CancellationTokenA token for canceling the request (optional).
Returns
- Task<HttpResponseMessage>
A task that represents the asynchronous operation. The task result contains the response.
Exceptions
- ArgumentNullException
Thrown if
method
oruri
is null.- HttpResponseException
Thrown if the response status code indicates a failure.
- HttpRequestException
Thrown if the request fails due to an underlying issue such as network connectivity, DNS failure, server certificate validation, or timeout.
- OperationCanceledException
Thrown if the operation is canceled via the cancellation token.
SendAsync<T>(HttpMethod, string, HttpContent?, CancellationToken)
Sends an asynchronous HTTP request with the specified method, URI, and payload, returning response body deserialized as the specified type.
public virtual Task<T?> SendAsync<T>(HttpMethod method, string uri, HttpContent? payload = null, CancellationToken cancellationToken = default)
Parameters
method
HttpMethodThe HTTP method to use for the request.
uri
stringThe URI to which the request is sent.
payload
HttpContentThe HTTP request payload content (optional).
cancellationToken
CancellationTokenA token for canceling the request (optional).
Returns
- Task<T>
A task that represents the asynchronous operation, with a result of the specified type.
Type Parameters
T
The type of the response object.
Exceptions
- ArgumentNullException
Thrown if
method
oruri
is null.- HttpResponseException
Thrown if the response status code indicates a failure.
- HttpRequestException
Thrown if the request fails due to an underlying issue such as network connectivity, DNS failure, server certificate validation, or timeout.
- HttpContentException
Thrown if the response body is empty or its media type is not supported.
- OperationCanceledException
Thrown if the operation is canceled via the cancellation token.
ToExceptionAsync(HttpResponseMessage, CancellationToken)
Converts an HttpResponseMessage into an appropriate exception.
protected virtual Task<HttpResponseException> ToExceptionAsync(HttpResponseMessage response, CancellationToken cancellationToken)
Parameters
response
HttpResponseMessageThe HTTP response message to convert.
cancellationToken
CancellationTokenA token for canceling the operation.
Returns
- Task<HttpResponseException>
A task that represents the asynchronous operation. The task result contains an HttpResponseException object that represents the error extracted from the response.
Remarks
This method endeavors to deserialize the response content into a ResponseErrorType, provided that the type is specified and implements the IHttpErrorResponse interface. Upon successful deserialization, the resulting data is transformed into an exception. If deserialization fails, a generic HttpResponseException is generated, incorporating the response's status code and a default error message.
Exceptions
- ArgumentNullException
Thrown if
response
is null.
- See Also
Events
AfterReceivingResponse
Occurs when an HTTP response has been received.
public event EventHandler<HttpResponseMessageEventArgs>? AfterReceivingResponse
Event Type
Remarks
This event is raised after an HTTP response is received but before the response is processed further. It provides a way for subscribers to inspect the HttpResponseMessage. This can be useful for logging response details, handling specific HTTP status codes, or modifying the response content or headers before they are processed by the rest of the application.
BeforeSendingRequest
Occurs when a new HTTP request message is about to be sent.
public event EventHandler<HttpRequestMessageEventArgs>? BeforeSendingRequest
Event Type
Remarks
This event provides an opportunity for subscribers to modify the HttpRequestMessage before it is sent. Common modifications include adding custom headers, changing request properties, or logging request information. Modifications made to the request in this event are included in the outgoing HTTP request.
Disposing
Occurs just before the HttpRestClient is disposed.
public event EventHandler<EventArgs>? Disposing
Event Type
Remarks
This event provides a way for subscribers to perform cleanup or other actions before the client is disposed.