6.65Custom HttpClientHandler

Created on Aug 17, 2026~3 min read

Although most interception logic should be implemented through DelegatingHandler, HttpClientHandler itself is also inheritable, allowing you to insert custom behavior at the layer closest to network I/O. This is suitable for scenarios that require deep control over the underlying request/response flow, such as:

  • Simulating specific network errors
  • Injecting monitoring before and after the TLS handshake
  • Bypassing the default Cookie or proxy handling logic
  • Capturing or transforming underlying network exceptions

The following is an example that inherits from HttpClientHandler, showing how to add a custom request header before sending the request and log the status code after receiving the response:

cs
public class CustomHttpHandler : HttpClientHandler{    /// <inheritdoc />    protected override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)    {        // Refer to the asynchronous SendAsync method        return base.Send(request, cancellationToken);    }    /// <inheritdoc />    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)    {        // Request pre-processing: add a custom request header        request.Headers.Add("Custom-Header", "Value");        // Send the request and get the response        var response = await base.SendAsync(request, cancellationToken);        // Response post-processing: log the response status code        Console.WriteLine($"Response status code: {response.StatusCode}");        return response;    }}

Next, configure and initialize CustomHttpHandler in the Program.cs or Startup.cs file:

csharp
// Enable for the default HttpClient clientservices.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new CustomHttpHandler());// To enable for a specifically named HttpClient client, configure as follows// services.AddHttpClient("weixin")//     .ConfigurePrimaryHttpMessageHandler(() => new CustomHttpHandler());

Note: ConfigurePrimaryHttpMessageHandler configures the underlying handler of the entire pipeline. It must be a concrete implementation of HttpMessageHandler (such as HttpClientHandler or SocketsHttpHandler), and cannot be a DelegatingHandler.