DotNETWeekly-io / DotNetWeekly

DotNet weekly newsletter
MIT License
201 stars 3 forks source link

【文章推荐】ASP.NET Core HttpClient 请求优化 #604

Closed gaufung closed 2 months ago

gaufung commented 3 months ago

https://www.youtube.com/watch?v=pJDIdIcOH6s&ab_channel=MilanJovanovi%C4%87

gaufung commented 2 months ago

HttpClient 是在 .NET 应用程序中广泛使用的类,它可以通过 HTTP 协议访问外部资源。其中在 ASP.NET Core 中可以更加优雅的方式使用他们。

  1. 使用 HttpClient 服务

首先将外部资源封装成一个服务,并且接受一个 HttpClient 对象

public class GitHubService 
{
    private readonly HttpClient _httpClient;
    public GitHubService(HttpClient httpClient) {
        _httpClient = httpClient;
    }
    public async Task<GithubFile[]?> GetFile(string org, string repo, string folder) {
         //...
    }
}

然后在依赖注入容器中注入该服务,并且配置相应的 HttpClient 基本信息

builder.Services.AddHttpClient<GitHubService>((sp, httpclient) =>
{
    var setting = sp.GetRequiredService<IOptions<GithubSetting>>().Value;
    httpclient.BaseAddress = new Uri(setting.BaseUrl);
});
  1. 使用 Refit

Refit 是一个 C# 的开源库,你只需要定义好配置访问资源的接口,该库可以生成相应的实现

public interface IGithubApi
{
    [Get("/repos/{org}/{repo}/contents/{folder}")]
    Task<GithubFile[]?> GetGithubFiles(string org, string repo, string folder);
}

这里 [Get("/repos/{org}/{repo}/contents/{folder}")] 注解是来自 Refit 的定义。然后将 IGithubApi 接口注入到容器中

builder.Services.AddRefitClient<IGithubApi>()
    .ConfigureHttpClient((sp, httpclient) =>
    {
        var setting = sp.GetRequiredService<IOptions<GithubSetting>>().Value;
        httpclient.BaseAddress = new Uri(setting.BaseUrl);
    });
  1. 继承 DelegatingHandler 抽象类

如果 HttpRequest 还有其他配置信息,比如授权的什么,我们实现一个 DeletingHandler

public class GithubAuthHandler : DelegatingHandler
{
    private readonly GithubSetting _githubSetting;
    public GithubAuthHandler(IOptions<GithubSetting> options) {
        _githubSetting = options.Value;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        request.Headers.Add("Accept", _githubSetting.Accept);
        request.Headers.Add("User-Agent", _githubSetting.UserAgent);
        return base.SendAsync(request, cancellationToken);
    }
}

然后在容器中配置该类

builder.Services.AddTransient<GithubAuthHandler>();
builder.Services.AddRefitClient<IGithubApi>()
    .ConfigureHttpClient((sp, httpclient) =>
    {
        var setting = sp.GetRequiredService<IOptions<GithubSetting>>().Value;
        httpclient.BaseAddress = new Uri(setting.BaseUrl);
    }).AddHttpMessageHandler<GithubAuthHandler>();