日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

使用自定义DelegatingHandler编写更整洁的Typed HttpClient

發(fā)布時(shí)間:2023/12/4 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用自定义DelegatingHandler编写更整洁的Typed HttpClient 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

使用自定義DelegatingHandler編寫更整潔的Typed HttpClient

簡(jiǎn)介

我寫了很多HttpClient[1],包括類型化的客戶端。自從我發(fā)現(xiàn)Refit[2]以來(lái),我只使用了那一個(gè),所以我只編寫了很少的代碼!但是我想到了你!你們中的某些人不一定會(huì)使用Refit,[3]因此,我將為您提供一些技巧,以使用HttpClient消息處理程序[4](尤其是DelegatingHandlers)[5]編寫具有最大可重用性的類型化HttpClient[6]

編寫類型化的HttpClient來(lái)轉(zhuǎn)發(fā)JWT并記錄錯(cuò)誤

這是要整理的HttpClient[7]

using DemoRefit.Models; using DemoRefit.Repositories; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks;namespace DemoRefit.HttpClients {public class CountryRepositoryClient : ICountryRepositoryClient{private readonly HttpClient _client;private readonly IHttpContextAccessor _httpContextAccessor;private readonly ILogger<CountryRepositoryClient> _logger;public CountryRepositoryClient(HttpClient client, ILogger<CountryRepositoryClient> logger, IHttpContextAccessor httpContextAccessor){_client = client;_logger = logger;_httpContextAccessor = httpContextAccessor;}public async Task<IEnumerable<Country>> GetAsync(){try{string accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");if (string.IsNullOrEmpty(accessToken)){throw new Exception("Access token is missing");}_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);var headers = _httpContextAccessor.HttpContext.Request.Headers;if (headers.ContainsKey("X-Correlation-ID") && !string.IsNullOrEmpty(headers["X-Correlation-ID"])){_client.DefaultRequestHeaders.Add("X-Correlation-ID", headers["X-Correlation-ID"].ToString());}using (HttpResponseMessage response = await _client.GetAsync("/api/democrud")){response.EnsureSuccessStatusCode();return await response.Content.ReadAsAsync<IEnumerable<Country>>();}}catch (Exception e){_logger.LogError(e, "Failed to run http query");return null;}}} }

這里有許多事情需要清理,因?yàn)樗鼈冊(cè)谀鷮⒃谕粦?yīng)用程序中編寫的每個(gè)客戶端中可能都是多余的:

?從HttpContext讀取訪問令牌?令牌為空時(shí),管理訪問令牌?將訪問令牌附加到HttpClient[8]進(jìn)行委派?從HttpContext讀取CorrelationId?將CorrelationId附加到HttpClient[9]進(jìn)行委托?使用EnsureSuccessStatusCode()驗(yàn)證Http查詢是否成功

編寫自定義的DelegatingHandler來(lái)處理冗余代碼

這是DelegatingHandler[10]

using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks;namespace DemoRefit.Handlers {public class MyDelegatingHandler : DelegatingHandler{private readonly IHttpContextAccessor _httpContextAccessor;private readonly ILogger<MyDelegatingHandler> _logger;public MyDelegatingHandler(IHttpContextAccessor httpContextAccessor, ILogger<MyDelegatingHandler> logger){_httpContextAccessor = httpContextAccessor;_logger = logger;}protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken){HttpResponseMessage httpResponseMessage;try{string accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");if (string.IsNullOrEmpty(accessToken)){throw new Exception($"Access token is missing for the request {request.RequestUri}");}request.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);var headers = _httpContextAccessor.HttpContext.Request.Headers;if (headers.ContainsKey("X-Correlation-ID") && !string.IsNullOrEmpty(headers["X-Correlation-ID"])){request.Headers.Add("X-Correlation-ID", headers["X-Correlation-ID"].ToString());}httpResponseMessage = await base.SendAsync(request, cancellationToken);httpResponseMessage.EnsureSuccessStatusCode();}catch (Exception ex){_logger.LogError(ex, "Failed to run http query {RequestUri}", request.RequestUri);throw;}return httpResponseMessage;}} }

如您所見,現(xiàn)在它封裝了用于同一應(yīng)用程序中每個(gè)HttpClient[11]的冗余邏輯 。

現(xiàn)在,清理后的HttpClient[12]如下所示:

using DemoRefit.Models; using DemoRefit.Repositories; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks;namespace DemoRefit.HttpClients {public class CountryRepositoryClientV2 : ICountryRepositoryClient{private readonly HttpClient _client;private readonly ILogger<CountryRepositoryClient> _logger;public CountryRepositoryClientV2(HttpClient client, ILogger<CountryRepositoryClient> logger){_client = client;_logger = logger;}public async Task<IEnumerable<Country>> GetAsync(){using (HttpResponseMessage response = await _client.GetAsync("/api/democrud")){try{return await response.Content.ReadAsAsync<IEnumerable<Country>>();}catch (Exception e){_logger.LogError(e, "Failed to read content");return null;}}}} }

好多了不是嗎?????

最后,讓我們將DelegatingHandler[13]附加到Startup.cs中的HttpClient[14]

using DemoRefit.Handlers; using DemoRefit.HttpClients; using DemoRefit.Repositories; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Refit; using System;namespace DemoRefit {public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddHttpContextAccessor();services.AddControllers();services.AddHttpClient<ICountryRepositoryClient, CountryRepositoryClientV2>().ConfigureHttpClient(c => c.BaseAddress = new Uri(Configuration.GetSection("Apis:CountryApi:Url").Value)).AddHttpMessageHandler<MyDelegatingHandler>();}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseHttpsRedirection();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}} }

使用Refit

如果您正在使用Refit[15],則絕對(duì)可以重用該DelegatingHandler[16]

例:

using DemoRefit.Handlers; using DemoRefit.HttpClients; using DemoRefit.Repositories; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Refit; using System;namespace DemoRefit {public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddHttpContextAccessor();services.AddControllers();services.AddRefitClient<ICountryRepositoryClient>().ConfigureHttpClient(c => c.BaseAddress = new Uri(Configuration.GetSection("Apis:CountryApi:Url").Value));.AddHttpMessageHandler<MyDelegatingHandler>();}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IWebHostEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseHttpsRedirection();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllers();});}} }

輪子介紹:

Refit是一個(gè)深受Square的 Retrofit 庫(kù)啟發(fā)的庫(kù),目前在github上共有star 4000枚,通過(guò)這個(gè)框架,可以把你的REST API變成了一個(gè)活的接口:

public interface IGitHubApi {[Get("/users/{user}")]Task<User> GetUser(string user); }

RestService類生成一個(gè)IGitHubApi的實(shí)現(xiàn),它使用HttpClient進(jìn)行調(diào)用:

var gitHubApi = RestService.For<IGitHubApi>("https://api.github.com");var octocat = await gitHubApi.GetUser("octocat");

查看更多:https://reactiveui.github.io/refit/

References

[1]?HttpClient:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netcore-3.0
[2]?Refit:?https://github.com/reactiveui/refit
[3]?Refit,:?https://github.com/reactiveui/refit
[4]?HttpClient消息處理程序:?https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/httpclient-message-handlers
[5]?DelegatingHandlers):?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?view=netframework-4.8
[6]?類型化HttpClient:?https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
[7]?鍵入的HttpClient:?https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
[8]?HttpClient:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netcore-3.0
[9]?HttpClient:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netcore-3.0
[10]?DelegatingHandler:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?view=netframework-4.8
[11]?HttpClient:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netcore-3.0
[12]?HttpClient:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netcore-3.0
[13]?DelegatingHandler:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?view=netframework-4.8
[14]?HttpClient:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netcore-3.0
[15]?Refit:?https://github.com/reactiveui/refit
[16]?DelegatingHandler:?https://docs.microsoft.com/en-us/dotnet/api/system.net.http.delegatinghandler?view=netframework-4.8

?

總結(jié)

以上是生活随笔為你收集整理的使用自定义DelegatingHandler编写更整洁的Typed HttpClient的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。