HeaderPropagation middleware: MessageHandler throws when used outside of a request
See original GitHub issueDescribe the bug
The MessageHandler relies on the Middleware to initialize HeaderPropagationValues.Headers to detect misconfiguration. However this means the Messagehandler can not be used outside of an http request and currently throws:
System.InvalidOperationException: The HeaderPropagationValues.Headers property has not been initialized. If using this HttpClient as part of an http request, register the header propagation middleware by adding 'app.UseHeaderPropagation() in the 'Configure(...)' method. Otherwise, use HeaderPropagationProcessor.ProcessRequest() before using the HttpClient.
To Reproduce
Steps to reproduce the behavior:
Code example
public void ConfigureServices(IServiceCollection services)
{
services
.AddHttpClient("test")
.AddHeaderPropagation();
services.AddHostedService<SampleHostedService>();
}
public class SampleHostedService : IHostedService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly HeaderPropagationProcessor _headerPropagationProcessor;
private readonly ILogger _logger;
public SampleHostedService(IHttpClientFactory httpClientFactory, HeaderPropagationProcessor headerPropagationProcessor, ILogger<SampleHostedService> logger)
{
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
_headerPropagationProcessor = headerPropagationProcessor ?? throw new ArgumentNullException(nameof(headerPropagationProcessor));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public Task StartAsync(CancellationToken cancellationToken)
{
return DoWorkAsync();
}
private async Task DoWorkAsync()
{
_logger.LogInformation("Background Service is working.");
var client = _httpClientFactory.CreateClient("test");
var result = await client.GetAsync("http://localhost:62013/forwarded");
_logger.LogInformation("Background Service:\n{result}", result);
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
Expected behavior
The HttpClient should work if used outside of a request or, if we don’t wont to support this use case, the exception should be updated to explain that such use case is not supported…
Possible solutions
I had investigated possible solutions. Not sure what is your preferred options and if we are still in time to do breaking changes on this middleware. Here are some options:
- Remove the check that throws the exception which means we would not be able anymore to detect misconfiguration. Can this be replaced with an analyzer? On top of the risk that the feature might not work due to misconfiguration, there is also the risk that having the valuefilter not execute (e.g. to set some headers with default values) when not called from outside a request can be unexpected.
- Update the exception message to also explain that a
HttpClientwith theHeaderPropagationMessageHandlercan not be used outside of a request. This is not ideal as it means you end up duplicating yourHttpClients configuration. - Extract the functionality from the Middleware to a generic Processor that can be called outside a http request. This will not change the middleware behaviour, but will allow to explicitly call the Processor when consuming an HttpClient outside of a http request. Ideally this will also include changing the valueFactory to receive a headers collection instead of the HttpContext, so that headers can be passed in different scenarios, for example when consuming messages from a queue, however I guess this scenario is out of scope for a middleware. See draft PR #12170 . The main issue I see with this approach is that when the processor is used directly you must take extra care as you need a different async context per request.
Looking forward for your feedback.
Thank you, Alessio
/cc @rynowak
Issue Analytics
- State:
- Created 4 years ago
- Comments:13 (10 by maintainers)
Top Results From Across the Web
HeaderPropagationMessageHan...
ASP.NET Core middleware to propagate HTTP headers from the incoming request to the outgoing HTTP Client requests. This is a backport to ASP....
Read more >Make HTTP requests using IHttpClientFactory in ASP.NET ...
Header propagation middleware Header propagation is an ASP.NET Core middleware to propagate HTTP headers from the incoming request to the ...
Read more >UseHeaderPropagation not recognized during debug run
Header propagation can only be used within the context of an HTTP request.' Am I just not seeing something here or what am...
Read more >Creating a proxy to another web api with Asp.net core
This post talks about writing a simple HTTP proxy logic in C# or ASP.NET Core. And allowing your project to proxy the request...
Read more >DelegatingHandler in ASP.NET Web API
Validate all outgoing requests in ASP.NET Web API using DelegatingHandler, SendAsync method in DelegatingHandler, Add Header to outbound request, Add Header ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Hello all, I am coming here from https://github.com/alefranz/HeaderPropagation/issues/6 as suggested by @alefranz.
I am starting to upgrade some projects at my company and header forwarding is being an issue for us. It is awesome that there is a standard package from the AspNetCore team that we can reference and use as model to how to solve similar problems, however this particular implementation is breaking for us. The header forwarding functionality should not break the regular httpclient flow when used from outside a request context.
We can create middlewares and http message handlers to have the exact behaviour we expect, specially after seen how it is done, however it leaves me feeling this “gap” where I see several packages officially supported by the AspNetCore team that don’t play well with each other. I would never have expected to not be able to use the same typed httpclient on a service if that service is consumed by a controller and by a background service.
Would it be a problem if the header forwarder message handler simply did nothing if there was no available http context to get headers from?
Any conclusion on this? I’m with @raphaabreu on this. Throwing an exception if there is no available http context relay does not work in all cases. The best possible solution is to just remove the throwing of the exception and don’t do anything.
In my case I’m using Refit and also resolving the typed clients in integration tests. We mainly want to use this package to pass diagnostics headers from envoy used for distributed tracing.
If the point of that exception is to detect misconstructions; you will know the moment the headers are not being propagated 😃