lai_transfer/src/Tool/HttpTool/HttpService.cs

302 lines
9.2 KiB
C#
Raw Normal View History

2025-10-23 18:12:06 +08:00
using Microsoft.Extensions.Logging;
using System.Text;
using System.Text.Json;
namespace lai_transfer.Tool.HttpTool;
public class HttpRequestConfig
{
public string? BaseUrl { get; set; }
public Dictionary<string, string> Headers { get; set; } = new();
public Dictionary<string, string> QueryParams { get; set; } = new();
public string? BearerToken { get; set; }
public TimeSpan? Timeout { get; set; }
public string? MediaType { get; set; } = "application/json";
public CancellationToken CancellationToken { get; set; } = CancellationToken.None;
}
public class HttpRequestConfig<T> : HttpRequestConfig
{
public T? Data { get; set; }
}
public interface IHttpService
{
Task<T?> GetAsync<T>(string url, HttpRequestConfig? config = null);
Task<string> GetStringAsync(string url, HttpRequestConfig? config = null);
Task<T?> PostAsync<T>(string url, object data, HttpRequestConfig? config = null);
Task<T?> PostAsync<T>(string url, HttpRequestConfig<T> config);
Task<T?> PutAsync<T>(string url, object data, HttpRequestConfig? config = null);
Task<bool> DeleteAsync(string url, HttpRequestConfig? config = null);
Task<Stream> GetStreamAsync(string url, HttpRequestConfig? config = null);
Task<byte[]> DownloadFileAsync(string url, HttpRequestConfig? config = null);
}
public class HttpService : IHttpService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<HttpService> _logger;
public HttpService(IHttpClientFactory httpClientFactory, ILogger<HttpService> logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD>HttpRequestMessage
/// </summary>
private HttpRequestMessage CreateHttpRequest(HttpMethod method, string url, HttpRequestConfig? config)
{
var requestUrl = BuildUrl(url, config);
var request = new HttpRequestMessage(method, requestUrl);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ
SetRequestHeaders(request, config);
return request;
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>URL<52><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
private string BuildUrl(string url, HttpRequestConfig? config)
{
if (config?.QueryParams == null || !config.QueryParams.Any())
return url;
var uriBuilder = new UriBuilder(url);
var query = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
foreach (var param in config.QueryParams)
{
query[param.Key] = param.Value;
}
uriBuilder.Query = query.ToString();
return uriBuilder.ToString();
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ
/// </summary>
private void SetRequestHeaders(HttpRequestMessage request, HttpRequestConfig? config)
{
if (config == null) return;
// <20><><EFBFBD><EFBFBD>Bearer Token
if (!string.IsNullOrEmpty(config.BearerToken))
{
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", config.BearerToken);
}
// <20><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ
foreach (var header in config.Headers)
{
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
// <20><><EFBFBD><EFBFBD>Content-Type
if (request.Content != null && !string.IsNullOrEmpty(config.MediaType))
{
request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(config.MediaType);
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD>HTTP<54><50><EFBFBD><EFBFBD>
/// </summary>
private async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpRequestConfig? config, string clientName = "DefaultClient")
{
using var httpClient = _httpClientFactory.CreateClient(clientName);
// <20><><EFBFBD>ó<EFBFBD>ʱ
if (config?.Timeout.HasValue == true)
{
httpClient.Timeout = config.Timeout.Value;
}
return await httpClient.SendAsync(request, config?.CancellationToken ?? CancellationToken.None);
}
/// <summary>
/// GET<45><54><EFBFBD><EFBFBD> - <20><><EFBFBD>ط<EFBFBD><D8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public async Task<T?> GetAsync<T>(string url, HttpRequestConfig? config = null)
{
try
{
var request = CreateHttpRequest(HttpMethod.Get, url, config);
var response = await SendAsync(request, config);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<T>(content, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
catch (Exception ex)
{
_logger.LogError(ex, "GET<45><54><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>: {Url}", url);
throw;
}
}
/// <summary>
/// GET<45><54><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
/// </summary>
public async Task<string> GetStringAsync(string url, HttpRequestConfig? config = null)
{
try
{
var request = CreateHttpRequest(HttpMethod.Get, url, config);
var response = await SendAsync(request, config);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "GET<45>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>: {Url}", url);
throw;
}
}
/// <summary>
/// POST<53><54><EFBFBD><EFBFBD>
/// </summary>
public async Task<T?> PostAsync<T>(string url, object data, HttpRequestConfig? config = null)
{
try
{
var request = CreateHttpRequest(HttpMethod.Post, url, config);
// <20>ж<EFBFBD>data<74>Dz<EFBFBD><C7B2><EFBFBD>string <20><><EFBFBD>ǵĻ<C7B5><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>
string json;
if (data is string str)
{
// <20><><EFBFBD><EFBFBD> data <20>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1>ʹ<EFBFBD><CAB9>
json = str;
}
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><C7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>Ϊ JSON
json = JsonSerializer.Serialize(data);
}
request.Content = new StringContent(json, Encoding.UTF8, config?.MediaType ?? "application/json");
var response = await SendAsync(request, config);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<T>(content, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
catch (Exception ex)
{
_logger.LogError(ex, "POST<53><54><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>: {Url}", url);
throw;
}
}
/// <summary>
/// POST<53><54><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ð汾
/// </summary>
public async Task<T?> PostAsync<T>(string url, HttpRequestConfig<T> config)
{
return await PostAsync<T>(url, config.Data!, config);
}
/// <summary>
/// PUT<55><54><EFBFBD><EFBFBD>
/// </summary>
public async Task<T?> PutAsync<T>(string url, object data, HttpRequestConfig? config = null)
{
try
{
var request = CreateHttpRequest(HttpMethod.Put, url, config);
var json = JsonSerializer.Serialize(data);
request.Content = new StringContent(json, Encoding.UTF8, config?.MediaType ?? "application/json");
var response = await SendAsync(request, config);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<T>(content, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
catch (Exception ex)
{
_logger.LogError(ex, "PUT<55><54><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>: {Url}", url);
throw;
}
}
/// <summary>
/// DELETE<54><45><EFBFBD><EFBFBD>
/// </summary>
public async Task<bool> DeleteAsync(string url, HttpRequestConfig? config = null)
{
try
{
var request = CreateHttpRequest(HttpMethod.Delete, url, config);
var response = await SendAsync(request, config);
return response.IsSuccessStatusCode;
}
catch (Exception ex)
{
_logger.LogError(ex, "DELETE<54><45><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>: {Url}", url);
throw;
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
/// </summary>
public async Task<Stream> GetStreamAsync(string url, HttpRequestConfig? config = null)
{
try
{
var request = CreateHttpRequest(HttpMethod.Get, url, config);
var response = await SendAsync(request, config);
response.EnsureSuccessStatusCode();
var stream = await response.Content.ReadAsStreamAsync();
// ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8><EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD>
response = null;
return stream;
}
catch (Exception ex)
{
_logger.LogError(ex, "<22><>ȡ<EFBFBD><C8A1>ʧ<EFBFBD><CAA7>: {Url}", url);
throw;
}
}
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
public async Task<byte[]> DownloadFileAsync(string url, HttpRequestConfig? config = null)
{
try
{
using var stream = await GetStreamAsync(url, config);
using var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
catch (Exception ex)
{
_logger.LogError(ex, "<22><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ʧ<EFBFBD><CAA7>: {Url}", url);
throw;
}
}
}