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));
}
///
/// 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($"{RedisPrefix.Code}:{RedisName.API}:{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);
}
}
}
}
}
}