C# HttpHelper 类
using System;
using System.Net.Http;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
public class VipSoftHttpHelper
{
private readonly HttpClient _httpClient;
private VipSoftHttpHelper() {
_httpClient = new HttpClient(new HttpClientHandler()
{
UseProxy = false,
// 其他配置...
});
_httpClient.DefaultRequestHeaders.Add("User-Agent", "C#-Client");
}
private static readonly Lazy<VipSoftHttpHelper> instance = new Lazy<VipSoftHttpHelper>(() => new VipSoftHttpHelper());
public static VipSoftHttpHelper Instance => instance.Value;
/// <summary>
/// POST 请求 Java API 接口
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="postData">请求数据对象</param>
/// <param name="timeoutSeconds">超时时间(秒)</param>
/// <param name="headers">请求头</param>
/// <returns>响应字符串</returns>
public string HttpPost(string url, object postData, int timeoutSeconds = 30, Dictionary<string, object> headers = null)
{
try
{
// 序列化数据
string jsonContent = Newtonsoft.Json.JsonConvert.SerializeObject(postData);
LogHelper.Debug($"HTTP POST: {url}, Timeout: {timeoutSeconds}s, Data: {jsonContent}");
// 使用 HttpRequestMessage 而不是直接修改 HttpClient
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(jsonContent, Encoding.UTF8, "application/json")
};
// 添加自定义请求头到本次请求
if (headers != null)
{
foreach (var header in headers)
{
if (header.Key.ToLower() == "content-type")
continue;
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
}
// 使用 CancellationToken 实现超时
CancellationTokenSource cts = new CancellationTokenSource();
try
{
if (timeoutSeconds > 0)
{
cts.CancelAfter(TimeSpan.FromSeconds(timeoutSeconds)); // 兼容旧版本
}
// 发送请求
HttpResponseMessage response = _httpClient.SendAsync(request, cts.Token).Result;
// 确保请求成功
response.EnsureSuccessStatusCode();
// 读取响应内容
return response.Content.ReadAsStringAsync().Result;
}
finally
{
cts?.Dispose();
}
}
catch (AggregateException ae)
{
throw ae.InnerException ?? ae;
}
catch (TaskCanceledException) when (timeoutSeconds > 0)
{
throw new TimeoutException($"请求超时 ({timeoutSeconds}秒)");
}
}
/// <summary>
/// 带泛型返回值的 POST 请求
/// </summary>
public T HttpPost<T>(string url, object postData, int timeoutSeconds = 30, Dictionary<string, object> headers = null)
{
string responseJson = HttpPost(url, postData, timeoutSeconds, headers);
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseJson);
}
/// <summary>
/// GET 请求
/// </summary>
public string HttpGet(string url, int timeoutSeconds = 30, Dictionary<string, object> headers = null)
{
try
{
// 使用 HttpRequestMessage 而不是直接修改 HttpClient
var request = new HttpRequestMessage(HttpMethod.Get, url);
// 添加自定义请求头到本次请求
if (headers != null)
{
foreach (var header in headers)
{
if (header.Key.ToLower() == "content-type")
continue;
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
}
// 使用 CancellationToken 实现超时
CancellationTokenSource cts = new CancellationTokenSource();
try
{
if (timeoutSeconds > 0)
{
cts.CancelAfter(TimeSpan.FromSeconds(timeoutSeconds)); // 兼容旧版本
}
// 发送请求
HttpResponseMessage response = _httpClient.SendAsync(request, cts.Token).Result;
// 确保请求成功
response.EnsureSuccessStatusCode();
// 读取响应内容
return response.Content.ReadAsStringAsync().Result;
}
finally
{
cts?.Dispose();
}
}
catch (AggregateException ae)
{
throw ae.InnerException ?? ae;
}
catch (TaskCanceledException) when (timeoutSeconds > 0)
{
throw new TimeoutException($"请求超时 ({timeoutSeconds}秒)");
}
}
/// <summary>
/// 带泛型返回值的 GET 请求
/// </summary>
public T HttpGet<T>(string url, int timeoutSeconds = 30, Dictionary<string, object> headers = null)
{
string responseJson = HttpGet(url, timeoutSeconds, headers);
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseJson);
}
}
✅ 代码优点
线程安全:使用 HttpRequestMessage 避免共享状态问题
兼容性好:使用 CancelAfter 兼容旧版 .NET Framework
资源管理:正确使用 try-finally 释放 CancellationTokenSource
异常处理:区分超时异常和其他异常
单例模式:正确复用 HttpClient 实例
本文来自博客园,作者:VipSoft 转载请注明原文链接:https://www.cnblogs.com/vipsoft/p/19235518
浙公网安备 33010602011771号