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>
|
|||
|
|
/// <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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|