Search code examples
c#refit

How to have OPTIONAL dynamic headers?


I am using Refit and would like to set OPTIONAL dynamic headers for some methods. For example if the user is logged in, I want to have header "UserId" and "AuthenticationToken", otherwise do NOT set the headers

[Post("/search")]
Task<SearchResponse> Search([Body]SearchRequest request, [Header("UserId")] string userId,[Header("AuthorizationToken")] string token);

Not sure if I pass null value to userId and token, the two headers will have null value or just be skipped (not included in the header)?

Thanks.


Solution

  • Using refit you can implement DelegatingHandler and then register that to do whatever you need to the http request before it is sent on. Here is adding an origin header to each request. Refit interface does not need to worry about it.

    public class AddOriginHeaderToRequest : DelegatingHandler
    {
        private const string ServiceNameSettingLocation = "AppConfig:Logging:ServiceName";
    
        private readonly IHttpContextAccessor httpContextAccessor;
    
        private readonly IConfiguration configuration;
    
        public AddOriginHeaderToRequest(IHttpContextAccessor httpContextAccessor, IConfiguration configuration)
        {
            this.httpContextAccessor = httpContextAccessor;
            this.configuration = configuration;
        }
    
        protected override async Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            var origin = this.configuration[AddOriginHeaderToRequest.SomethingThatShouldBeDefined];
    
            if (!(request.Headers.Contains("origin") || request.Headers.Contains("Origin")) && origin != null)
            {
                request.Headers.Add("origin", origin);
            }
    
            return await base.SendAsync(request, cancellationToken);
        }
    }
    

    Then register it like this:

    services.AddTransient<AddOriginHeaderToRequest>();
    

    Then the refit client can be registered like this (this is a redacted version of one of our nuget packages so will hopefully give an idea of how it works):

    public static IHttpClientBuilder AddHttpClientWithDefaultHandlers(
        this IServiceCollection services,
        string name,
        Action<HttpClient> configureClient)
    {
        return services.AddHttpClient(name, configureClient)
            .AddHttpMessageHandler<AddOriginHeaderToRequest>();
    }
    

    Then in our service we register our refit handler like this:

    services.AddHttpClientWithRefitAndDefaultHandlers<ImyHttpClient>(
        "myHttpClient",
        c =>
        {
            c.BaseAddress = new Uri(appSettings.Value.AppConfig.SomeUrl);
        });
    

    This can be simplified but we have a number of different handlers that massage our http requests in a standard way.

    I hope that gives you a pointer to how it could work.