using System.Collections.Specialized;
using System.Net.Http.Headers;
using System.Text;
using DS.Module.Core.Extensions;
using Newtonsoft.Json;
namespace DS.Module.Core
{
///
/// 提供对HTTP请求的低级别访问
///
public class ApiFox : IDisposable
{
readonly HttpClient http;
///
/// 基URI
///
public Uri? BaseUri { get { return http.BaseAddress; } set { http.BaseAddress = value; } }
///
/// 默认请求头
///
public HttpRequestHeaders DefaultHeaders => http.DefaultRequestHeaders;
///
/// 在发送网络请求之前的事件
///
public event EventHandler? BeforeSend;
///
/// 在发送网络请求完成时的事件
///
public event EventHandler? Completed;
///
/// 初始化
///
/// 连接池使用时间,默认为30分钟
public ApiFox(int pooledMinutes = 30)
{
var handler = new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(pooledMinutes)
};
http = new(handler);
http.DefaultRequestHeaders.Add("User-Agent", $"X-{nameof(ApiFox)}");
http.DefaultRequestHeaders.Add("Accept", "application/json, text/plain");
}
///
/// 发起请求
///
/// 请求结果的类型
/// 请求Url
/// 查询字符串的键值对
///
/// 为null或空字符串
public async Task> GetAsync(string url, NameValueCollection? keyValues = null)
{
string queryString = string.Empty;
if (keyValues != null && keyValues.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (string key in keyValues.Keys)
{
var values = keyValues.GetValues(key);
if (values?.Length > 0)
{
for (int i = 0; i < values.Length; i++)
{
sb.Append($"&{key}={values[i]}");
}
}
}
if (sb.Length > 0) //移除首个&符
sb.Remove(0, 1);
queryString = sb.ToString();
}
if (!queryString.IsNullOrEmpty())
url = url.LastOrDefault() == '?' ? url + queryString : url + "?" + queryString;
var response = await SendRequestAsync(HttpMethod.Get, url);
T? data = default;
if (response != null && response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
data = JsonConvert.DeserializeObject(json);
return DataResult.Success(data);
}
return DataResult.Failed(response.ReasonPhrase);
}
///
/// 发起请求
///
/// 请求结果的类型
/// 请求Url
/// 请求参数对象
///
/// 为null或空字符串
public async Task> PostAsync(string url, object? requestParams = null)
{
var response = await SendRequestAsync(HttpMethod.Post, url, requestParams);
T? data = default;
if (response != null && response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
data = JsonConvert.DeserializeObject(json);
return DataResult.Success(data);
}
return DataResult.Failed(response.ReasonPhrase);
}
///
/// 发起HTTP请求
///
/// 请求方法
/// 请求Url
/// 请求参数
///
/// 为null
/// 为null或空字符串
/// 不等于 GET/POST/PUT/Delete 中的任何一个请求方法
public async Task SendRequestAsync(HttpMethod method, string url, object? requestParams = null)
{
ArgumentNullException.ThrowIfNull(method);
ArgumentException.ThrowIfNullOrEmpty(url);
Uri? reqUri = default;
if (BaseUri == null)
{
if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out Uri? uri))
throw new ArgumentException("给定的URL格式无效", nameof(url));
reqUri = new Uri(url);
}
else
{
reqUri = new(BaseUri, url);
}
OnBeforeSend(new BeforeSendEventArgs
{
RequestHeaders = http.DefaultRequestHeaders,
RequestParameter = requestParams,
RequestUri = reqUri
});
HttpResponseMessage? response = null;
if (method == HttpMethod.Get)
{
response = await http.GetAsync(reqUri);
}
else if (method == HttpMethod.Post)
{
string json = JsonConvert.SerializeObject(requestParams);
var jsonRequest = new StringContent(json, Encoding.UTF8, "application/json");
response = await http.PostAsync(reqUri, jsonRequest);
}
else if (method == HttpMethod.Put)
{
string json = JsonConvert.SerializeObject(requestParams);
var jsonRequest = new StringContent(json, Encoding.UTF8, "application/json");
response = await http.PutAsync(reqUri, jsonRequest);
}
else if (method == HttpMethod.Delete)
{
response = await http.DeleteAsync(reqUri);
}
else
{
throw new NotSupportedException($"不支持的请求方法:{method.Method}");
}
OnCompleted(new CompleteEventArgs
{
RequestUri = reqUri,
Response = response
});
return response;
}
///
/// 在发送网络请求之前调用
///
/// 事件参数
protected virtual void OnBeforeSend(BeforeSendEventArgs e)
{
BeforeSend?.Invoke(this, e);
}
///
/// 在发送网络请求完成时调用
///
/// 事件参数
protected virtual void OnCompleted(CompleteEventArgs e)
{
Completed?.Invoke(this, e);
}
///
/// 释放网络连接
///
public void Dispose() => http?.Dispose();
}
///
/// 发送网络请求之前的事件参数
///
public class BeforeSendEventArgs : EventArgs
{
///
/// 远程请求的URI
///
public Uri RequestUri { get; internal set; }
///
/// 请求标头
///
public HttpRequestHeaders RequestHeaders { get; internal set; }
///
/// 请求参数
///
public object? RequestParameter { get; set; }
}
///
/// 发送网络请求完成的事件参数
///
public class CompleteEventArgs : EventArgs
{
///
/// 远程请求的URI
///
public Uri RequestUri { get; internal set; }
///
/// 网络响应对象
///
public HttpResponseMessage Response { get; internal set; }
}
}