You typically don't use a "global" HttpClient's DefaultRequestHeaders. You would want to create an HttpRequestMessage and use SendAsync. This gives that session a unique header dictionary that is segregated from all other requests.
HttpClient's DefaultRequestHeaders are not thread-safe. So if you modify them in the middle of another request, you will crash.
What you should do is inject HttpClientFactory and then create clients from that. Continue to use the HttpRequestMessage/SendAsync pattern (or use straight-up GetAsync, PostAsync, etc.) all while avoiding DefaultRequestHeaders (if you use the factory's CreateClient() method).
If you use a factory, you can use DefaultRequestHeaders if you create a named or typed HttpClient object from the factory. You will probably want to do this for your specific use-case you mentioned in your question.
Example
- Start a new Azure Function project.
- Add
Microsoft.Azure.Functions.Extensions and Microsoft.Extensions.Http packages via NuGet.
- Add a new class, name it
Startup.cs. Make it look like this:
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Http.Headers;
[assembly: FunctionsStartup(typeof(MyAzureFunction.Startup))]
namespace MyAzureFunction
{
public sealed class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddHttpClient("MyAuthorizedClient", client =>
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "<token>");
});
}
}
}
- By default, the function's class and the function itself is
static. Make sure to remove the static keyword. Then, add a constructor. We will inject the factory via constructor:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace MyAzureFunction
{
public sealed class Function1
{
private readonly IHttpClientFactory _httpClientFactory;
public Function1(IHttpClientFactory httpContextFactory)
{
_httpClientFactory = httpContextFactory;
}
[FunctionName("Function1")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
//
// make a request on the authorized client
var authorizedClient = _httpClientFactory.CreateClient("MyAuthorizedClient");
using (var response = await authorizedClient
.GetAsync(new Uri("https://www.example.com")))
{
var objRecved = await response.Content.ReadAsAsync<object>();
return new OkObjectResult(new { data = objRecved });
}
//
// make a request on the non-authorized client using it's own header collection
var nonAuthorizedClient = _httpClientFactory.CreateClient();
using (var request = new HttpRequestMessage(
HttpMethod.Get, new Uri("https://www.example.com")))
{
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", "<token>");
using(var response = await nonAuthorizedClient.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var objRecved = await response.Content.ReadAsAsync<object>();
return new OkObjectResult(new { data = objRecved });
}
}
}
}
}