Concerns
Concerns allow to add behavior to a section of your web application by intercepting requests and responses. The framework allows any handler to be extended by using concerns. The following example will add a custom HTTP header to every response generated by the server:
using GenHTTP.Engine.Internal;
using GenHTTP.Modules.IO;
var customConcern = Concern.From(async (request, content) =>
{
var response = await content.HandleAsync(request);
return response?.Rebuild()
.Header("X-Custom-Header", "Custom Concern")
.Build();
});
var handler = Content.From(Resource.FromString("Hello World"))
.Add(customConcern);
await Host.Create()
.Handler(handler)
.RunAsync();This code uses a shortcut provided by the Concern class of the IO module
to reduce the boilerplate required to implement IConcern. The full version of
the example above would look like this:
using GenHTTP.Api.Content;
using GenHTTP.Api.Infrastructure;
using GenHTTP.Api.Protocol;
using GenHTTP.Engine.Internal;
using GenHTTP.Modules.IO;
var handler = Content.From(Resource.FromString("Hello World"))
.Add(new CustomConcernBuilder());
await Host.Create()
.Handler(handler)
.RunAsync();
public class CustomConcern : IConcern
{
public IHandler Content { get; }
public CustomConcern(IHandler content)
{
Content = content;
}
public ValueTask PrepareAsync(IServer server) => Content.PrepareAsync(server);
public async ValueTask<IResponse?> HandleAsync(IRequest request)
{
var response = await Content.HandleAsync(request);
return response?.Rebuild()
.Header("X-Custom-Header", "Custom Concern")
.Build();
}
}
public class CustomConcernBuilder : IConcernBuilder
{
public IConcern Build(IHandler content)
{
return new CustomConcern(content);
}
}The GenHTTP SDK uses the same mechanism to achieve functionality such as compression or support for CORS.
If your concern reads additional headers or generates additional responses, you can implement
IDocumentedConcern instead to add this functionality to the specification generated by the
Open API concern.