302 lines
9.2 KiB
C#
302 lines
9.2 KiB
C#
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>
|
||
/// ÅäÖÃHttpRequestMessage
|
||
/// </summary>
|
||
private HttpRequestMessage CreateHttpRequest(HttpMethod method, string url, HttpRequestConfig? config)
|
||
{
|
||
var requestUrl = BuildUrl(url, config);
|
||
var request = new HttpRequestMessage(method, requestUrl);
|
||
|
||
// ÉèÖÃÇëÇóÍ·
|
||
SetRequestHeaders(request, config);
|
||
|
||
return request;
|
||
}
|
||
|
||
/// <summary>
|
||
/// ¹¹½¨ÍêÕûURL£¨°üº¬²éѯ²ÎÊý£©
|
||
/// </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>
|
||
/// ÉèÖÃÇëÇóÍ·
|
||
/// </summary>
|
||
private void SetRequestHeaders(HttpRequestMessage request, HttpRequestConfig? config)
|
||
{
|
||
if (config == null) return;
|
||
|
||
// ÉèÖÃBearer Token
|
||
if (!string.IsNullOrEmpty(config.BearerToken))
|
||
{
|
||
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", config.BearerToken);
|
||
}
|
||
|
||
// ÉèÖÃ×Ô¶¨ÒåÇëÇóÍ·
|
||
foreach (var header in config.Headers)
|
||
{
|
||
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||
}
|
||
|
||
// ÉèÖÃContent-Type
|
||
if (request.Content != null && !string.IsNullOrEmpty(config.MediaType))
|
||
{
|
||
request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(config.MediaType);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ·¢ËÍHTTPÇëÇó
|
||
/// </summary>
|
||
private async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpRequestConfig? config, string clientName = "DefaultClient")
|
||
{
|
||
using var httpClient = _httpClientFactory.CreateClient(clientName);
|
||
|
||
// ÉèÖó¬Ê±
|
||
if (config?.Timeout.HasValue == true)
|
||
{
|
||
httpClient.Timeout = config.Timeout.Value;
|
||
}
|
||
|
||
return await httpClient.SendAsync(request, config?.CancellationToken ?? CancellationToken.None);
|
||
}
|
||
|
||
/// <summary>
|
||
/// GETÇëÇó - ·µ»Ø·ºÐÍÀàÐÍ
|
||
/// </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ÇëÇóʧ°Ü: {Url}", url);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// GETÇëÇó - ·µ»Ø×Ö·û´®
|
||
/// </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×Ö·û´®ÇëÇóʧ°Ü: {Url}", url);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// POSTÇëÇó
|
||
/// </summary>
|
||
public async Task<T?> PostAsync<T>(string url, object data, HttpRequestConfig? config = null)
|
||
{
|
||
try
|
||
{
|
||
var request = CreateHttpRequest(HttpMethod.Post, url, config);
|
||
// ÅжÏdataÊDz»ÊÇstring ²»Êǵϰ²ÅÐòÁл°
|
||
string json;
|
||
if (data is string str)
|
||
{
|
||
// Èç¹û data ÒѾÊÇ×Ö·û´®£¬Ö±½ÓʹÓÃ
|
||
json = str;
|
||
}
|
||
else
|
||
{
|
||
// Èç¹ûÊǶÔÏó£¬ÐòÁл¯Îª 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ÇëÇóʧ°Ü: {Url}", url);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// POSTÇëÇó - ·ºÐÍÅäÖð汾
|
||
/// </summary>
|
||
public async Task<T?> PostAsync<T>(string url, HttpRequestConfig<T> config)
|
||
{
|
||
return await PostAsync<T>(url, config.Data!, config);
|
||
}
|
||
|
||
/// <summary>
|
||
/// PUTÇëÇó
|
||
/// </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ÇëÇóʧ°Ü: {Url}", url);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// DELETEÇëÇó
|
||
/// </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ÇëÇóʧ°Ü: {Url}", url);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ÏÂÔØÎļþÁ÷
|
||
/// </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();
|
||
|
||
// ×ªÒÆËùÓÐȨ£¬µ÷Ó÷½¸ºÔðÊÍ·Å
|
||
response = null;
|
||
return stream;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "»ñÈ¡Á÷ʧ°Ü: {Url}", url);
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// ÏÂÔØÎļþ×Ö½ÚÊý×é
|
||
/// </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, "ÏÂÔØÎļþʧ°Ü: {Url}", url);
|
||
throw;
|
||
}
|
||
}
|
||
} |