NET 6 HttpHelper

发布时间 2023-11-29 16:01:18作者: 蒙先生

封装了常见http请求,目的是提高代码质量、简化开发流程,代码中的 out HttpResponseHeaders headers 输出返回头的是华为云Token体系用到的,其他场景目前未看到过;

在使用过程中需要再Program中注入

//注入HttpClient
builder.Services.AddHttpClient();
builder.Services.AddSingleton<IHttpClient, StandardHttpClient>();

namespace Http.Utils
{
    /// <summary>
    /// IHttpClient
    /// </summary>
    public interface IHttpClient
    {
        /// <summary>
        /// 提交GET请求并获取对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        T? Get<T>(string url, int timeOut = 5);

        /// <summary>
        ///  get返回流
        /// </summary>
        /// <param name="url"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        Task<Stream?> Get(string url, int timeOut = 5);

        /// <summary>
        /// 提交POST请求并获取对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="text"></param>
        /// <param name="url"></param>
        /// <param name="contentType"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        T? Post<T>(string text, string url, string contentType = "text/xml", int timeOut = 5);

        /// <summary>
        /// 处理http POST请求,返回数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="text"></param>
        /// <param name="url"></param>
        /// <param name="contentType"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        Task<T?> PostAsync<T>(string text, string url, string contentType = "text/xml", int timeOut = 5);

        /// <summary>
        /// 处理http POST请求,返回数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="bytes"></param>
        /// <param name="url"></param>
        /// <param name="contentType"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        Task<T?> PostAsync<T>(byte[] bytes, string url, string contentType = "application/octet-stream",
            int timeOut = 5);

        /// <summary>
        /// http POST方法
        /// </summary>
        /// <param name="text">post的参数</param>
        /// <param name="url">提交地址</param>
        /// <param name="headerAddition"></param>
        /// <param name="contentType"></param>
        /// <param name="timeOut">超时时间</param>
        /// <returns></returns>
        Task<T?> PostAndHeaderAsync<T>(string text, string url, Dictionary<string, string>? headerAddition = null, string contentType = "application/json", int timeOut = 3);

        /// <summary>
        /// http POST方法
        /// </summary>
        /// <param name="text">post的参数</param>
        /// <param name="url">提交地址</param>
        /// <param name="headerAddition"></param>
        /// <param name="contentType"></param>
        /// <param name="timeOut">超时时间</param>
        /// <returns></returns>
        T? PostAndHeader<T>(string text, string url, Dictionary<string, string>? headerAddition = null,
            string contentType = "application/json", int timeOut = 3);

        /// <summary>
        /// http POST方法
        /// </summary>
        /// <param name="text">post的参数</param>
        /// <param name="url">提交地址</param>
        /// <param name="headerAddition"></param>
        /// <param name="contentType"></param>
        /// <param name="timeOut">超时时间</param>
        /// <returns></returns>
        HttpResponseMessage PostAndHeader(string text, string url, Dictionary<string, string>? headerAddition = null,
            string contentType = "application/json", int timeOut = 3);

        /// <summary>
        /// http POST方法
        /// </summary>
        /// <param name="text">post的参数</param>
        /// <param name="url">提交地址</param>
        /// <param name="headers">输入响应头</param>
        /// <param name="headerAddition"></param>
        /// <param name="contentType"></param>
        /// <param name="timeOut">超时时间</param>
        /// <returns></returns>
        T? PostOutHeader<T>(string text, string url, out HttpResponseHeaders headers,
            Dictionary<string, string>? headerAddition = null, string contentType = "application/json",
            int timeOut = 3);

        /// <summary>
        /// 处理http GET请求,返回数据
        /// </summary>
        /// <param name="url">请求的url地址</param>
        /// <param name="headerAddition"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        T? GetAndHeader<T>(string url, Dictionary<string, string>? headerAddition = null, int timeOut = 3);

        /// <summary>
        /// 处理http GET请求,返回数据
        /// </summary>
        /// <param name="url">请求的url地址</param>
        /// <param name="headerAddition"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        Task<T?> GetAsync<T>(string url, Dictionary<string, string>? headerAddition = null,
            int timeOut = 3);
    }
}


/// <summary>
/// HttpClient
/// </summary>
public class StandardHttpClient : IHttpClient
{
    private readonly IHttpClientFactory _httpClientFactory;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="httpClientFactory"></param>
    public StandardHttpClient(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
    {
        //直接确认,否则打不开
        return true;
    }

    /// <inheritdoc />
    public Stream? Download(string text, string url, int timeOut, out string contentType, string certPath = "", string certPassword = "")
    {
        try
        {
            //设置最大连接数
            ServicePointManager.DefaultConnectionLimit = 200;

            //设置https验证方式
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
            }

            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.Timeout = timeOut * 1000;

            //设置POST的数据类型和长度
            request.ContentType = "text/xml";
            var data = Encoding.UTF8.GetBytes(text);
            request.ContentLength = data.Length;

            //是否使用证书
            if (!string.IsNullOrEmpty(certPath))
            {
                var cert = new X509Certificate2(certPath, certPassword);
                request.ClientCertificates.Add(cert);
            }
            ////往服务器写入数据
            var reqStream = request.GetRequestStream();

            reqStream.Write(data, 0, data.Length);
            reqStream.Close();

            ////获取服务端返回
            var response = (HttpWebResponse)request.GetResponse();
            contentType = response.ContentType;

            return response.GetResponseStream();
        }
        catch (Exception e)
        {
            throw;
        }
    }

    /// <inheritdoc />
    public T? Get<T>(string url, int timeOut = 5)
    {
        var result = "";

        HttpResponseMessage? response = null;

        //请求url以获取数据
        try
        {
            var client = _httpClientFactory.CreateClient();
            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            //获取服务器返回
            var httpRequest = new HttpRequestMessage(HttpMethod.Get, url);

            response = client.Send(httpRequest);

            //获取HTTP返回数据
            var sr = new StreamReader(response.Content.ReadAsStream(), Encoding.UTF8);

            result = sr.ReadToEnd().Trim();
            sr.Close();
        }
        catch
        {
            throw;
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    /// <inheritdoc />
    public async Task<Stream?> Get(string url, int timeOut = 5)
    {
        HttpResponseMessage? response = null;

        //请求url以获取数据
        try
        {
            var client = _httpClientFactory.CreateClient();
            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            //获取服务器返回
            var httpRequest = new HttpRequestMessage(HttpMethod.Get, url);

            response = await client.SendAsync(httpRequest);

            if (response.IsSuccessStatusCode)
            {
                var imageBytes = await response.Content.ReadAsByteArrayAsync();
                return new MemoryStream(imageBytes);
            }
            else
            {
                // 处理HTTP请求失败
                return null;
            }
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }
    }

    /// <inheritdoc />
    public T? Post<T>(string text, string url, string contentType = "text/xml", int timeOut = 5)
    {
        var result = "";

        HttpResponseMessage? response = null;

        MemoryStream postStream = new();
        try
        {
            var data = Encoding.UTF8.GetBytes(text);

            postStream.Write(data, 0, data.Length);
            postStream.Seek(0L, SeekOrigin.Begin);

            var hc = new StreamContent(postStream);
            hc.Headers.ContentType = new MediaTypeHeaderValue(contentType);

            var httpRequest = new HttpRequestMessage(HttpMethod.Post, url);
            httpRequest.Content = hc;

            var client = _httpClientFactory.CreateClient();
            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            response = client.Send(httpRequest);

            //获取服务端返回数据
            var sr = new StreamReader(response.Content.ReadAsStream(), Encoding.UTF8);

            result = sr.ReadToEnd().Trim();

            sr.Close();
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    /// <inheritdoc />
    public async Task<T?> PostAsync<T>(string text, string url, string contentType = "text/xml", int timeOut = 5)
    {
        var result = "";

        HttpResponseMessage? response = null;

        try
        {
            MemoryStream postStream = new();

            var data = Encoding.UTF8.GetBytes(text);

            postStream.Write(data, 0, data.Length);
            postStream.Seek(0L, SeekOrigin.Begin);

            var hc = new StreamContent(postStream);
            hc.Headers.ContentType = new MediaTypeHeaderValue(contentType);

            var httpRequest = new HttpRequestMessage(HttpMethod.Post, url);
            httpRequest.Content = hc;

            var client = _httpClientFactory.CreateClient();

            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            response = await client.SendAsync(httpRequest);

            //获取服务端返回数据
            var sr = new StreamReader(await response.Content.ReadAsStreamAsync(), Encoding.UTF8);

            result = (await sr.ReadToEndAsync()).Trim();

            sr.Close();
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    /// <inheritdoc />
    public async Task<T?> PostAsync<T>(byte[] bytes, string url, string contentType = "application/octet-stream", int timeOut = 5)
    {
        var result = "";

        HttpResponseMessage? response = null;

        try
        {
            var array = new ByteArrayContent(bytes);

            //数据类型,需要对应
            array.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            var client = _httpClientFactory.CreateClient();

            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            response = await client.PostAsync(url, array);

            var sr = new StreamReader(await response.Content.ReadAsStreamAsync(), Encoding.UTF8);

            result = (await sr.ReadToEndAsync()).Trim();

            sr.Close();
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    /// <inheritdoc />
    public async Task<T?> PostAndHeaderAsync<T>(string text, string url, Dictionary<string, string>? headerAddition = null, string contentType = "application/json", int timeOut = 3)
    {
        var result = "";//返回结果

        HttpResponseMessage? response = null;

        try
        {
            MemoryStream postStream = new();

            var data = Encoding.UTF8.GetBytes(text);

            postStream.Write(data, 0, data.Length);
            postStream.Seek(0L, SeekOrigin.Begin);

            var hc = new StreamContent(postStream);

            hc.Headers.ContentType = new MediaTypeHeaderValue(contentType);

            if (headerAddition != null)
            {
                AddRequestHeaders(hc.Headers, headerAddition);
            }

            var httpRequest = new HttpRequestMessage(HttpMethod.Post, url);
            httpRequest.Content = hc;

            var client = _httpClientFactory.CreateClient();

            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            response = await client.SendAsync(httpRequest);

            //获取服务端返回数据
            var sr = new StreamReader(await response.Content.ReadAsStreamAsync(), Encoding.UTF8);

            result = (await sr.ReadToEndAsync()).Trim();

            sr.Close();
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    /// <inheritdoc />
    public T? PostAndHeader<T>(string text, string url, Dictionary<string, string>? headerAddition = null, string contentType = "application/json", int timeOut = 3)
    {
        var result = "";//返回结果

        HttpResponseMessage? response = null;

        try
        {
            MemoryStream postStream = new();

            var data = Encoding.UTF8.GetBytes(text);

            postStream.Write(data, 0, data.Length);
            postStream.Seek(0L, SeekOrigin.Begin);

            var hc = new StreamContent(postStream);

            hc.Headers.ContentType = new MediaTypeHeaderValue(contentType);

            if (headerAddition != null)
            {
                AddRequestHeaders(hc.Headers, headerAddition);
            }

            var httpRequest = new HttpRequestMessage(HttpMethod.Post, url);
            httpRequest.Content = hc;

            var client = _httpClientFactory.CreateClient();

            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            response = client.Send(httpRequest);

            //获取服务端返回数据
            var sr = new StreamReader(response.Content.ReadAsStream(), Encoding.UTF8);

            result = sr.ReadToEnd().Trim();

            sr.Close();
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    /// <inheritdoc />
    public HttpResponseMessage PostAndHeader(string text, string url, Dictionary<string, string>? headerAddition = null, string contentType = "application/json", int timeOut = 3)
    {
        MemoryStream postStream = new();

        var data = Encoding.UTF8.GetBytes(text);

        postStream.Write(data, 0, data.Length);
        postStream.Seek(0L, SeekOrigin.Begin);

        var hc = new StreamContent(postStream);

        hc.Headers.ContentType = new MediaTypeHeaderValue(contentType);

        if (headerAddition != null)
        {
            AddRequestHeaders(hc.Headers, headerAddition);
        }

        var httpRequest = new HttpRequestMessage(HttpMethod.Post, url);
        httpRequest.Content = hc;

        var client = _httpClientFactory.CreateClient();

        client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

        return client.Send(httpRequest);
    }

    /// <inheritdoc />
    public T? PostOutHeader<T>(string text, string url, out HttpResponseHeaders headers, Dictionary<string, string>? headerAddition = null, string contentType = "application/json", int timeOut = 3)
    {
        var result = "";//返回结果

        HttpResponseMessage? response = null;

        try
        {
            MemoryStream postStream = new();

            var data = Encoding.UTF8.GetBytes(text);

            postStream.Write(data, 0, data.Length);
            postStream.Seek(0L, SeekOrigin.Begin);

            var hc = new StreamContent(postStream);

            hc.Headers.ContentType = new MediaTypeHeaderValue(contentType);

            if (headerAddition != null)
            {
                AddRequestHeaders(hc.Headers, headerAddition);
            }

            var httpRequest = new HttpRequestMessage(HttpMethod.Post, url);
            httpRequest.Content = hc;

            var client = _httpClientFactory.CreateClient();

            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            response = client.Send(httpRequest);

            headers = response.Headers;

            //获取服务端返回数据
            var sr = new StreamReader(response.Content.ReadAsStream(), Encoding.UTF8);

            result = sr.ReadToEnd().Trim();

            sr.Close();
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    /// <inheritdoc />
    public T? GetAndHeader<T>(string url, Dictionary<string, string>? headerAddition = null, int timeOut = 3)
    {
        var result = "";

        HttpResponseMessage? response = null;

        //请求url以获取数据
        try
        {
            var client = _httpClientFactory.CreateClient();
            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            //获取服务器返回
            var httpRequest = new HttpRequestMessage(HttpMethod.Get, url);

            if (headerAddition != null)
                AddRequestHeaders(httpRequest.Headers, headerAddition);

            response = client.Send(httpRequest);

            //获取HTTP返回数据
            var sr = new StreamReader(response.Content.ReadAsStream(), Encoding.UTF8);

            result = sr.ReadToEnd().Trim();
            sr.Close();
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    /// <inheritdoc />
    public async Task<T?> GetAsync<T>(string url, Dictionary<string, string>? headerAddition = null, int timeOut = 3)
    {
        var result = "";

        HttpResponseMessage? response = null;

        //请求url以获取数据
        try
        {
            var client = _httpClientFactory.CreateClient();
            client.Timeout = new TimeSpan(0, 0, timeOut * 1000);

            //获取服务器返回
            var httpRequest = new HttpRequestMessage(HttpMethod.Get, url);

            if (headerAddition != null)
                AddRequestHeaders(httpRequest.Headers, headerAddition);

            response = await client.SendAsync(httpRequest);

            //获取HTTP返回数据
            var sr = new StreamReader(await response.Content.ReadAsStreamAsync(), Encoding.UTF8);

            result = (await sr.ReadToEndAsync()).Trim();
            sr.Close();
        }
        finally
        {
            //关闭连接和流
            response?.Dispose();
        }

        return JsonConvert.DeserializeObject<T>(result);
    }

    private static void AddRequestHeaders(HttpHeaders headers, Dictionary<string, string>? headerAddition)
    {
        if (headerAddition == null) return;

        foreach (var pair in headerAddition)
        {
            headers.Add(pair.Key, pair.Value);
        }
    }
}