使用 HttpClient 來呼叫其他的服務取得資料,要加上 header 有幾種作法,底下來看看怎麼用
環境: Dotnet 9
直接加
最直接的作法是在每個 request 前加上 header
1 2 3 4 5 6 7 8 9 10
| builder.Services.AddHttpClient();
app.MapGet("/weatherforecast", (HttpRequest request, [FromServices] HttpClient httpClient) => { httpClient.DefaultRequestHeaders.Add("custom-data", "jimmy test"); return httpClient.GetFromJsonAsync<IEnumerable<WeatherForecast>>( $"http://localhost:5183/weatherforecast"); }) .WithName("GetWeatherForecast") .WithOpenApi();
|
使用 DelegatingHandler
上面的作法很簡單,但每個都要自己加,變得很難以管理
c# 有提供 DelegatingHandler 的做法,這等於是 interceptor 中介,也可以說是 middleware,讓我們可以統一的加上 header 的行為
建立一個 CustomHttpInterceptor.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class CustomHttpInterceptor : DelegatingHandler { private readonly IHttpContextAccessor _httpContextAccessor;
public CustomHttpInterceptor(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request.Headers.Add("custom-data", "jimmy test");
return await base.SendAsync(request, cancellationToken); } }
|
回到 Program.cs
需要調整 AddHttpClient
的設定
1 2 3 4
| builder.Services.AddTransient<CustomHttpInterceptor>();
builder.Services.AddHttpClient("test") .AddHttpMessageHandler<CustomHttpInterceptor>();
|
上面這些做完原本的注入可以不用改,持續用 HttpClient
,也可以改用 IHttpClientFactory
1 2 3 4 5 6 7 8
| app.MapGet("/weatherforecast", (HttpRequest request, [FromServices] IHttpClientFactory httpClientFactory) => { var httpClient = httpClientFactory.CreateClient("test"); return httpClient.GetFromJsonAsync<IEnumerable<WeatherForecast>>( $"http://localhost:5183/weatherforecast"); }) .WithName("GetWeatherForecast") .WithOpenApi();
|
這樣呼叫出去的 API 就都會統一加上 custom-data
在 header 上啦!
Reference