Skip to content

Custom HTTP client

FantasticFiasco edited this page Nov 4, 2019 · 6 revisions

The HTTP client has the responsibility of sending log events over the network to a receiving log server. The default client works in many circumstances, but some log servers might place certain requirements on the sender. Perhaps a certain HTTP header is required, or the log server is using a self signed certificate?

This sink is supporting these cases by letting you provide your own implementation of IHttpClient, defined below.

/// <summary>
/// Interface responsible for posting HTTP requests.
/// </summary>
public interface IHttpClient : IDisposable
{
  /// <summary>
  /// Sends a POST request to the specified Uri as an asynchronous operation.
  /// </summary>
  /// <param name="requestUri">The Uri the request is sent to.</param>
  /// <param name="content">The HTTP request content sent to the server.</param>
  /// <returns>The task object representing the asynchronous operation.</returns>
  Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content);
}

Example: The basic authenticated HTTP client

Close your eyes and imagine we have a log server that requires basic authentication. The default HTTP client does not support any authentication protocol, which would force us to implement a custom client. It is not as hard as it sounds, it only means that we have to implement IHttpClient and provide the implementation to the sink.

Lets start with the implementation. Below is the code required to authenticate the sender to the log server.

public class BasicAuthenticatedHttpClient : IHttpClient
{
  private readonly HttpClient client;

  public BasicAuthenticatedHttpClient(string username, string password)
  {
    if (username == null) throw new ArgumentNullException(nameof(username));
    if (password == null) throw new ArgumentNullException(nameof(password));

    client = CreateHttpClient(username, password);
  }

  public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content) =>
    client.PostAsync(requestUri, content);

  public void Dispose() =>
    client.Dispose();

  private static HttpClient CreateHttpClient(string username, string password)
  {
    var client = new HttpClient();

    var schema = "Basic";
    var parameter = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));

    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(schema, parameter);

    return client;
  }
}

With the custom client in place, we specify it when configuring the sink.

ILogger logger = new LoggerConfiguration()
  .WriteTo.Http(
    "www.mylogs.com",
    httpClient: new BasicAuthenticatedHttpClient("username", "password"))
  .CreateLogger();

And now we are done, requests to the log server are basic authenticated!

Clone this wiki locally