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");
|
_cache.TryAdd($"{RedisPrefix.Code}:{RedisName.API}:{nameof(ConfigKey.RelocationFinishTask)}", $"Task/RelocationFinishTask");
|
}
|
|
/// <summary>
|
/// POST请求
|
/// </summary>
|
/// <param name="url">请求URL</param>
|
/// <param name="content">请求内容</param>
|
/// <param name="mediaType">媒体类型</param>
|
/// <param name="config">请求配置</param>
|
/// <returns></returns>
|
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;
|
}
|
|
|
/// <summary>
|
/// POST请求
|
/// </summary>
|
/// <param name="url">请求URL</param>
|
/// <param name="content">请求内容</param>
|
/// <param name="mediaType">媒体类型</param>
|
/// <param name="config">请求配置</param>
|
/// <returns></returns>
|
public HttpResponseResult<TResponse> Post<TResponse>(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<TResponse> result = new HttpResponseResult<TResponse>
|
{
|
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<TResponse>(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<TResponse> Get<TResponse>(string url, HttpRequestConfig? config = null)
|
{
|
url = BaseAPI.WMSBaseUrl + _cache.Get(url);
|
HttpResponseResult httpResponseResult = Get(url, config);
|
|
HttpResponseResult<TResponse> result = new HttpResponseResult<TResponse>
|
{
|
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<TResponse>(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;
|
}
|
|
/// <summary>
|
/// 执行HTTP请求
|
/// </summary>
|
private async Task<HttpResponseResult> ExecuteAsync(Func<HttpClient, Task<HttpResponseMessage>> 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<string, IEnumerable<string>>();
|
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;
|
}
|
|
/// <summary>
|
/// 创建HttpClient
|
/// </summary>
|
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;
|
}
|
|
|
/// <summary>
|
/// 设置请求头
|
/// </summary>
|
private void SetRequestHeaders(HttpRequestMessage request, Dictionary<string, string>? headers)
|
{
|
if (headers != null)
|
{
|
foreach (var header in headers)
|
{
|
if (!request.Headers.Contains(header.Key))
|
{
|
request.Headers.Add(header.Key, header.Value);
|
}
|
}
|
}
|
}
|
|
}
|
}
|