using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection.Metadata; using System.Text; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using WIDESEAWCS_Common; using WIDESEAWCS_Common.HttpEnum; using WIDESEAWCS_Core.Caches; namespace WIDESEA_Core { public class HttpClientHelper { private readonly IHttpClientFactory _httpClientFactory; private readonly ICacheService _cache; public HttpClientHelper(IHttpClientFactory httpClientFactory, ICacheService cache, IConfiguration configuration = null) { _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory)); _cache = cache ?? throw new ArgumentNullException(nameof(cache)); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.CreateTaskInboundAsync)}", $"Task/CreateTaskInbound"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.GetTasksLocation)}", $"Task/GetTasksLocation"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.OutboundFinishTaskAsync)}", $"Task/OutboundFinishTask"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.InboundFinishTaskAsync)}", $"Task/InboundFinishTask"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.GetOutBoundTrayTaskAsync)}", $"Task/GetOutBoundTrayTask"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.CreateTaskInboundTrayAsync)}", $"Task/CreateTaskInboundTray"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.GroupPalletAsync)}", $"Stock/GroupPalletAsync"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.ChangePalletAsync)}", $"Stock/ChangePalletAsync"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.SplitPalletAsync)}", $"Stock/SplitPalletAsync"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.UpdateTaskByStatus)}", $"Task/UpdateTaskByStatus"); _cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.TransferCheck)}", $"LocationInfo/TransferCheck"); } /// /// POST请求 /// /// 请求URL /// 请求内容 /// 媒体类型 /// 请求配置 /// public HttpResponseResult Post(string url, string content, string contentType = "application/json", HttpRequestConfig? config = null) { HttpResponseResult httpResponseResult = Task.Run(async () => { return await ExecuteAsync(async (client) => { var request = new HttpRequestMessage(HttpMethod.Post, url); request.Content = new StringContent(content ?? string.Empty, Encoding.UTF8, contentType); SetRequestHeaders(request, config?.Headers); return await client.SendAsync(request); }, config, $"POST {url}"); }).GetAwaiter().GetResult(); httpResponseResult.ApiUrl = url; return httpResponseResult; } public HttpResponseResult Get(string url, HttpRequestConfig? config = null) { HttpResponseResult httpResponseResult = Task.Run(async () => { return await ExecuteAsync(async (client) => { var request = new HttpRequestMessage(HttpMethod.Get, url); SetRequestHeaders(request, config?.Headers); return await client.SendAsync(request); }, config, $"GET {url}"); }).GetAwaiter().GetResult(); httpResponseResult.ApiUrl = url; return httpResponseResult; } /// /// POST请求 /// /// 请求URL /// 请求内容 /// 媒体类型 /// 请求配置 /// public HttpResponseResult Post(string url, string content, string contentType = "application/json", HttpRequestConfig? config = null) { url = BaseAPI.WMSBaseUrl + _cache.Get($"{RedisPrefix.Code}:{RedisName.API}:{url}"); HttpResponseResult httpResponseResult = Post(url, content, contentType, config); HttpResponseResult result = new HttpResponseResult { IsSuccess = httpResponseResult.IsSuccess, StatusCode = httpResponseResult.StatusCode, Content = httpResponseResult.Content, Headers = httpResponseResult.Headers, Duration = httpResponseResult.Duration, ErrorMessage = httpResponseResult.ErrorMessage, Exception = httpResponseResult.Exception }; if (result.IsSuccess && !string.IsNullOrEmpty(result.Content)) { try { TResponse? response = JsonConvert.DeserializeObject(result.Content); if (response != null) { result.Data = response; } else { result.IsSuccess = false; result.ErrorMessage = "反序列化结果为null"; } } catch (Exception ex) { result.IsSuccess = false; result.ErrorMessage = $"反序列化失败: {ex.Message}"; result.Exception = ex; } } return result; } public HttpResponseResult Get(string url, HttpRequestConfig? config = null) { url = BaseAPI.WMSBaseUrl + _cache.Get(url); HttpResponseResult httpResponseResult = Get(url, config); HttpResponseResult result = new HttpResponseResult { IsSuccess = httpResponseResult.IsSuccess, StatusCode = httpResponseResult.StatusCode, Content = httpResponseResult.Content, Headers = httpResponseResult.Headers, Duration = httpResponseResult.Duration, ErrorMessage = httpResponseResult.ErrorMessage, Exception = httpResponseResult.Exception }; if (result.IsSuccess && !string.IsNullOrEmpty(result.Content)) { try { TResponse? response = JsonConvert.DeserializeObject(result.Content); if (response != null) { result.Data = response; } else { result.IsSuccess = false; result.ErrorMessage = "反序列化结果为null"; } } catch (Exception ex) { result.IsSuccess = false; result.ErrorMessage = $"反序列化失败: {ex.Message}"; result.Exception = ex; } } return result; } /// /// 执行HTTP请求 /// private async Task ExecuteAsync(Func> requestFunc, HttpRequestConfig? config, string requestInfo) { var result = new HttpResponseResult(); var stopwatch = System.Diagnostics.Stopwatch.StartNew(); config ??= new HttpRequestConfig(); try { using var client = CreateHttpClient(config); HttpResponseMessage? response = null; Exception? lastException = null; // 重试机制 for (int retry = 0; retry <= config.MaxRetryCount; retry++) { try { response = await requestFunc(client); if (response.StatusCode == System.Net.HttpStatusCode.OK) break; } catch (Exception ex) when (retry < config.MaxRetryCount) { lastException = ex; if (config.EnableLogging) { // TODO:日志记录 } await Task.Delay(config.RetryIntervalMs, default); } } if (response == null) { throw lastException ?? new HttpRequestException("请求失败"); } result.StatusCode = response.StatusCode; result.IsSuccess = response.IsSuccessStatusCode; // 读取响应内容 result.Content = await response.Content.ReadAsStringAsync(); // 获取响应头 result.Headers = new Dictionary>(); foreach (var header in response.Headers) { result.Headers[header.Key] = header.Value; } foreach (var header in response.Content.Headers) { result.Headers[header.Key] = header.Value; } if (config.EnableLogging) { // TODO:日志记录 } } catch (Exception ex) { result.IsSuccess = false; result.ErrorMessage = ex.Message; result.Exception = ex; if (config.EnableLogging) { // TODO:日志记录 } } finally { stopwatch.Stop(); result.Duration = stopwatch.ElapsedMilliseconds; } return result; } /// /// 创建HttpClient /// private HttpClient CreateHttpClient(HttpRequestConfig config) { var client = _httpClientFactory.CreateClient(); client.Timeout = TimeSpan.FromMilliseconds(config.TimeoutMs); // 设置默认请求头 client.DefaultRequestHeaders.Clear(); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); return client; } /// /// 设置请求头 /// private void SetRequestHeaders(HttpRequestMessage request, Dictionary? headers) { if (headers != null) { foreach (var header in headers) { if (!request.Headers.Contains(header.Key)) { request.Headers.Add(header.Key, header.Value); } } } } } }