.net core 5.0 之IHttpClientFactory
官网介绍:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/http-requests?view=aspnetcore-5.0
引入NuGet包(涉及到策略才引用)
Microsoft.Extensions.Http.Polly
appsettings.json:
"Services": { "userapi": "http://192.168.0.236:7202", "fileapi": "http://192.168.0.236:7205", "conv19vaccineapi": "http://192.168.0.236:7410" },
Startup:
IConfigurationSection section = Configuration.GetSection("Services"); List<string> list = new List<string>(); var childes = section.GetChildren(); foreach (var configSection in childes) { var conKey = configSection.Key; } var serviceList = Configuration.GetSection("Services").GetChildren(); var fallbackResponse = new HttpResponseMessage { Content = new StringContent("服务器内部错误"), StatusCode = HttpStatusCode.RequestTimeout }; foreach (ConfigurationSection configSection in serviceList) { services.AddHttpClient(configSection.Key, async (provider, client) => { var httpcontextaccessor = provider.GetService<IHttpContextAccessor>(); var token = await httpcontextaccessor.HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken); client.BaseAddress = new Uri(configSection.Value); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); client.DefaultRequestHeaders.Add("X-ClientIP", httpcontextaccessor.HttpContext.Connection.RemoteIpAddress?.ToString()); }) //异常 .AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>() //快速反馈 .FallbackAsync(fallbackResponse, async b => { await Task.CompletedTask; })) // 重试 .AddPolicyHandler(Policy<HttpResponseMessage> .Handle<TimeoutRejectedException>() .WaitAndRetryAsync( new[] { TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(200) } ) ) // 超时 .AddPolicyHandler( Policy.TimeoutAsync<HttpResponseMessage>( TimeSpan.FromSeconds(180) ) ); }
控制器调用
public class BaseController : Controller { private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHttpClientFactory _httpClientFactory; public BaseController(IHttpContextAccessor httpContextAccessor, IHttpClientFactory httpClientFactory) { _httpContextAccessor = httpContextAccessor; _httpClientFactory = httpClientFactory; } /// <summary> /// 公共Post请求方法 /// </summary> /// <param name="servciesname">服务名称</param> /// <param name="url">服务地址</param> /// <param name="json">数据</param> /// <returns></returns> protected async Task<IActionResult> ClientPostAsync(string servciesname, string url, object json) { //var token = await GetTokenAsync(); //if (string.IsNullOrEmpty(token)) //{ // throw new Exception("登录信息过期,请重新登录"); //} using (var _httpClient = _httpClientFactory.CreateClient(servciesname)) { url = _httpClient.BaseAddress + url; // _httpClient.SetBearerToken(token); var response = await _httpClient.PostAsJsonAsync(url, json); if (response.StatusCode == HttpStatusCode.OK) { var result = await response.Content.ReadAsStringAsync(); return Ok(result); } else if (response.StatusCode == HttpStatusCode.Unauthorized) { return Ok(new { Result = 401, Message = "登录信息已经过期,请重新登录" }); } return Ok(new { Result = 404, Message = "数据请求失败" }); } } protected async Task<string> ClientPostResultStringAsync(string servciesname, string url, object json) { //var token = await GetTokenAsync(); //if (string.IsNullOrEmpty(token)) //{ // throw new Exception("登录信息过期,请重新登录"); //} using (var _httpClient = _httpClientFactory.CreateClient(servciesname)) { url = _httpClient.BaseAddress + url; // _httpClient.SetBearerToken(token); var response = await _httpClient.PostAsJsonAsync(url, json); if (response.StatusCode == HttpStatusCode.OK) return response.Content.ReadAsStringAsync().Result; return ""; } } /// <summary> /// Get请求 /// </summary> /// <param name="servicesname"></param> /// <param name= "url"></param> /// <returns></returns> protected async Task<IActionResult> ClientGetAsync(string servicesname, string url) { //var token = await GetTokenAsync(); //if (string.IsNullOrEmpty(token)) //{ // throw new Exception("登录信息过期,请重新登录"); //} try { using (var _httpClient = _httpClientFactory.CreateClient(servicesname)) { url = _httpClient.BaseAddress + url; // _httpClient.SetBearerToken(token); var response = await _httpClient.GetAsync(url); if (response.StatusCode == HttpStatusCode.OK) { var result = await response.Content.ReadAsStringAsync(); return Ok(result); } else if (response.StatusCode == HttpStatusCode.Unauthorized) { return Ok(new { Result = 401, Message = "登录信息已经过期,请重新登录" }); } return Ok(new { Result = 404, Message = "数据请求失败" }); } } catch (Exception e) { return Ok(new { Result = 404, Message = "数据请求失败" }); } } /// <summary> /// Delete请求 /// </summary> /// <param name="servicesname"></param> /// <param name="url"></param> /// <returns></returns> protected async Task<IActionResult> ClientDeleteAsync(string servicesname, string url) { // var token = await GetTokenAsync(); //if (string.IsNullOrEmpty(token)) //{ // throw new Exception("登录信息过期,请重新登录"); //} using (var _httpClient = _httpClientFactory.CreateClient(servicesname)) { url = _httpClient.BaseAddress + url; // _httpClient.SetBearerToken(token); var response = await _httpClient.DeleteAsync(url); if (response.StatusCode == HttpStatusCode.OK) { return Ok(response.Content.ReadAsStringAsync().Result); } else if (response.StatusCode == HttpStatusCode.Unauthorized) { return Ok(new { Result = 401, Message = "登录信息已经过期,请重新登录" }); } return Ok(new { Result = 404, Message = "数据请求失败" }); } } /// <summary> /// Put请求 /// </summary> /// <param name="servicesname"></param> /// <param name="url"></param> /// <param name="json"></param> /// <returns></returns> protected async Task<IActionResult> ClientPutAsync(string servicesname, string url, object json) { //var token = await GetTokenAsync(); //if (string.IsNullOrEmpty(token)) //{ // throw new Exception("登录信息过期,请重新登录"); //} using (var _httpClient = _httpClientFactory.CreateClient(servicesname)) { url = _httpClient.BaseAddress + url; // _httpClient.SetBearerToken(token); var response = await _httpClient.PutAsJsonAsync(url, json); if (response.StatusCode == HttpStatusCode.OK) { var result = await response.Content.ReadAsStringAsync(); return Ok(result); } else if (response.StatusCode == HttpStatusCode.Unauthorized) { return Ok(new { Result = 401, Message = "登录信息已经过期,请重新登录" }); } return Ok(new { Result = 404, Message = "数据请求失败" }); } } /// <summary> /// Post文件传输 /// </summary> /// <param name="servicesname"></param> /// <param name="url"></param> /// <param name="file"></param> /// <returns></returns> protected async Task<IActionResult> ClientPostFileAsync(string servicesname, string url, IFormFile file) { using (var _httpClient = _httpClientFactory.CreateClient(servicesname)) { url = _httpClient.BaseAddress + url; var stream = file.OpenReadStream(); var httpContent = new MultipartFormDataContent(); httpContent.Add(new StreamContent(stream), "file", file.FileName); var response = await _httpClient.PostAsync(url, httpContent); if (response.StatusCode == HttpStatusCode.OK) { var result = await response.Content.ReadAsStringAsync(); return Ok(result); } else if (response.StatusCode == HttpStatusCode.Unauthorized) { return Ok(new { Result = 401, Message = "登录信息已经过期,请重新登录" }); } return Ok(new { Result = 404, Message = "数据请求失败" }); } } }