Getting started

edit

Install a package

Each feature is its own package. Add the ones you need to a project:

dotnet package add Meziantou.Framework.Http.Caching
dotnet package add Meziantou.Framework.Http.Hsts
dotnet package add Meziantou.Framework.Http.ServerSideRequestForgery

The introduction lists every package. The types are in these namespaces:

PackageNamespace
Meziantou.Framework.Http, .Hsts, .HtpasswdMeziantou.Framework.Http
Meziantou.Framework.Http.CachingMeziantou.Framework.Http.Caching
Meziantou.Framework.Http.Caching.InMemory, .Sqlite, .RedisMeziantou.Framework.Http.Caching.InMemory, .Sqlite, .Redis
Meziantou.Framework.Http.RecordingMeziantou.Framework.Http.Recording
Meziantou.Framework.Http.ServerSideRequestForgeryMeziantou.Framework.Http.ServerSideRequestForgery

The examples of this documentation omit the using directives.

Add a handler to an HttpClient

The caching, HSTS, SSRF and recording features are DelegatingHandlers. Create the handler with the handler that sends the requests, usually a SocketsHttpHandler, and give it to the HttpClient:

var policies = new HstsDomainPolicyCollection(includePreloadDomains: true);
using var client = new HttpClient(new HstsClientHandler(new SocketsHttpHandler(), policies), disposeHandler: true);

// Automatically upgrade to HTTPS as github.com is in the HSTS preload list
using var response = await client.GetAsync("http://github.com");

Every request sent by this client goes through HstsClientHandler before it reaches the network. With disposeHandler: true, disposing the client disposes the handlers.

A handler is a link of a chain: its inner handler can itself be a DelegatingHandler. Each page says what a handler needs from the handlers below it; for instance, the SSRF protection needs a SocketsHttpHandler, and the HSTS handler follows the redirects itself.

Register a handler with IHttpClientFactory

With IHttpClientFactory (the Microsoft.Extensions.Http package), register the handler in the container and add it to a named or typed client with AddHttpMessageHandler. The factory creates the primary handler and sets the InnerHandler, so use a constructor that takes no inner handler:

services.AddTransient(_ => new HstsClientHandler(policies));
services.AddHttpClient("api")
        .AddHttpMessageHandler<HstsClientHandler>()
        .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler());

AddHttpMessageHandler fails when the handler already has an inner handler.

Next steps