NetFramework 模拟请求(get/post):HttpHelper

HttpHelper

using Common.Extends;
using CustFramework.Constants;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Web;

namespace Common.Helper
{
    /// <summary>
    /// 模拟请求帮助类
    /// </summary>
    public static class HttpHelper
    {
        /// <summary>
        /// nlog util
        /// </summary>
        private static readonly NLogHelper NLogHelper = new NLogHelper();

        /// <summary>
        /// 获取 或 设置 跟踪code
        /// </summary>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string GetOrSetTraceCode(string defaultValue = null)
        {
            //  为空情况(弃用,自定义HttpContext会导致异步报错):
            //  1.异步编程:在 async/await 之后,执行可能跳转到另一个线程,该线程没有原始的 HttpContext。
            //  2.Web API 自托管(Self - Host):不依赖于 IIS 和 System.Web。
            //  3.后台线程:手动启动的 Task.Run 或 ThreadPool 线程。
            //  4.OWIN 中间件:在某些 OWIN 管道阶段可能无法访问。
            //  5.单元测试
            if (HttpContext.Current?.Items == null)
            {
                //var mockContext = new HttpContext(
                //    new HttpRequest("Mock", "https://Mock.com", ""),
                //    new HttpResponse(new StringWriter())
                //);
                //var httpContextAccessorType = Type.GetType("System.Web.HttpContext, System.Web");
                //var currentProperty = httpContextAccessorType?.GetProperty("Current");
                //currentProperty?.SetValue(null, mockContext);
                //HttpContext.Current = mockContext;
                return defaultValue ?? string.Empty;
            }
            var traceCode = HttpContext.Current.Items[AppSettingConstant.HttpTraceCodeKey]?.ToString();
            if (string.IsNullOrWhiteSpace(traceCode))
            {
                traceCode = string.IsNullOrWhiteSpace(defaultValue) ? Guid.NewGuid().ToString() : defaultValue;
                HttpContext.Current.Items[AppSettingConstant.HttpTraceCodeKey] = traceCode;
            }
            return traceCode;
        }

        /// <summary>
        /// Post 请求
        /// </summary>
        /// <typeparam name="T">请求参数 类型</typeparam>
        /// <typeparam name="ReturnT">返回对象 类型</typeparam>
        /// <param name="url">请求路径</param>
        /// <param name="postData">氢气参数</param>
        /// <returns></returns>
        public static ReturnT Post<T, ReturnT>(string url, T postData)
        {
            var postDataStr = postData.ToJson();
            var rspStr = Post(url, postDataStr);
            return rspStr.IsNullOrWhiteSpace() ? default : rspStr.ToObject<ReturnT>();
        }

        /// <summary>
        /// Post 请求
        /// </summary>
        /// <typeparam name="T">请求参数 类型</typeparam>
        /// <typeparam name="ReturnT">返回对象 类型</typeparam>
        /// <param name="url">请求路径</param>
        /// <param name="postData">氢气参数</param>
        /// <returns></returns>
        public static ReturnT Post<ReturnT>(string url, string postDataStr)
        {
            var rspStr = Post(url, postDataStr);
            return rspStr.IsNullOrWhiteSpace() ? default : rspStr.ToObject<ReturnT>();
        }

        /// <summary>
        /// Post 请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postDataStr"></param>
        /// <returns></returns>
        public static string Post(string url, string postDataStr)
        {
            var rspTuple = SimulateRequest(HttpType.Post, url, postDataStr: postDataStr);
            return rspTuple.Item1 ? rspTuple.Item2 : string.Empty;
        }

        /// <summary>
        /// Post 请求
        /// </summary>
        /// <typeparam name="ReturnT">返回对象 类型</typeparam>
        /// <param name="url">模拟请求路径</param>
        /// <param name="headers">hander参字典</param>
        /// <param name="isHttpSuccessStatusOnly200">http成功状态码,是否只判断200  ? 只有200才算请求成功 : 非200也需要处理响应(NTQS)</param>
        /// <returns>item1:请求成功/失败;item2:请求响应数据;item3:错误信息</returns>
        public static Tuple<bool, ReturnT, string> GetTupleT<ReturnT>(string url, Dictionary<string, string> headers = null, bool isHttpSuccessStatusOnly200 = true)
        {
            var rspTuple = GetTupleStr(url, headers, isHttpSuccessStatusOnly200: isHttpSuccessStatusOnly200);
            ReturnT returnT = rspTuple.Item1 ? rspTuple.Item2.ToObject<ReturnT>() : default;
            return new Tuple<bool, ReturnT, string>(rspTuple.Item1, returnT, rspTuple.Item3);
        }

        /// <summary>
        /// Post 请求
        /// </summary>
        /// <param name="url">模拟请求路径</param>
        /// <param name="headers">hander参字典</param>
        /// <param name="isHttpSuccessStatusOnly200">http成功状态码,是否只判断200  ? 只有200才算请求成功 : 非200也需要处理响应(NTQS)</param>
        /// <returns>item1:请求成功/失败;item2:请求响应数据;item3:错误信息</returns>
        public static Tuple<bool, string, string> GetTupleStr(string url, Dictionary<string, string> headers = null, bool isHttpSuccessStatusOnly200 = true)
        {
            return SimulateRequest(HttpType.Get, url, headers: headers, isHttpSuccessStatusOnly200: isHttpSuccessStatusOnly200);
        }

        /// <summary>
        /// 模拟请求
        /// </summary>
        /// <param name="httpType">模拟请求类型:GET / POST</param>
        /// <param name="url">模拟请求路径</param>
        /// <param name="postDataStr">Post请求参数</param>
        /// <param name="headers">hander参字典</param>
        /// <param name="isHttpSuccessStatusOnly200">http成功状态码,是否只判断200  ? 只有200才算请求成功 : 非200也需要处理响应(NTQS)</param>
        /// <returns>item1:请求成功/失败;item2:请求响应数据;item3:错误信息</returns>
        public static Tuple<bool, string, string> SimulateRequest(HttpType httpType, string url, string postDataStr = null, Dictionary<string, string> headers = null, bool isHttpSuccessStatusOnly200 = true)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var rspStr = string.Empty;
            Stream reqStream = null;
            HttpWebResponse response = null;
            Stream rspStream = null;
            StreamReader rspReader = null;

            var httpTypeStr = httpType.ToString();
            var traceCode = $"HttpHelper.{httpTypeStr}({url}) TraceCode:{GetOrSetTraceCode()} ";
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                //  设置模拟请求类型
                request.Method = httpTypeStr;
                //request.UserAgent = "Mozilla/5.0";
                request.KeepAlive = false;
                request.ReadWriteTimeout = 20 * 1000;
                request.ContentType = "application/json;charset=utf-8";

                // 添加请求头
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        request.Headers[header.Key] = header.Value;
                    }
                }

                //  post请求绑定body参数
                if (httpType == HttpType.Post && !postDataStr.IsNullOrWhiteSpace())
                {
                    traceCode += $"Param:{postDataStr} ";
                    var postData = Encoding.UTF8.GetBytes(postDataStr);
                    request.ContentLength = postData.Length;
                    reqStream = request.GetRequestStream();
                    reqStream.Write(postData, 0, postData.Length);
                }

                //  默认编码  
                var encoding = string.Empty;
                try
                {
                    response = (HttpWebResponse)request.GetResponse();
                    rspStream = response.GetResponseStream();
                    encoding = response.ContentEncoding;
                }
                catch (WebException webEx)
                {
                    //  接口返回的状态码不正常,但是要求处理响应
                    if (!isHttpSuccessStatusOnly200 && webEx.Response is HttpWebResponse errorResponse && (int)errorResponse.StatusCode == 422)
                    {
                        rspStream = errorResponse.GetResponseStream();
                        encoding = errorResponse.ContentEncoding;
                    }
                    else
                        throw webEx;
                }
                if (encoding == null || encoding.Length < 1)
                    encoding = "UTF-8";

                rspReader = new StreamReader(rspStream, Encoding.GetEncoding(encoding));
                rspStr = rspReader.ReadToEnd();
            }
            catch (Exception ex)
            {
                var message = $"{traceCode} Error:{ex.Message}";

                NLogHelper.Error(ex, message);
                return new Tuple<bool, string, string>(false, string.Empty, $"Http[{httpTypeStr}]请求异常 {ex.Message}");
            }
            finally
            {
                if (rspReader != null) rspReader.Close();
                if (rspStream != null) rspStream.Close();
                if (response != null) response.Close();
                if (reqStream != null) reqStream.Close();

                stopwatch.Stop();
                var actionDuration = new TimeSpan(stopwatch.ElapsedTicks).ToString();
                NLogHelper.Debug($"{traceCode}Duration:{actionDuration}\r\nResponse:{rspStr}");
            }
            return new Tuple<bool, string, string>(true, rspStr, string.Empty);
        }
    }

    /// <summary>
    /// 模拟请求类型
    /// </summary>
    public enum HttpType
    {
        Get,
        Post
    }
}

 

2.Error

2.1.接口http状态返回的不是200,但是要求获取响应结果

                //  默认编码  
                var encoding = string.Empty;
                try
                {
                    response = (HttpWebResponse)request.GetResponse();
                    rspStream = response.GetResponseStream();
                    encoding = response.ContentEncoding;
                }
                catch (WebException webEx)
                {
                    //  接口返回的状态码不正常,但是要求处理响应
                    if (!isHttpSuccessStatusOnly200 && webEx.Response is HttpWebResponse errorResponse && (int)errorResponse.StatusCode == 422)
                    {
                        rspStream = errorResponse.GetResponseStream();
                        encoding = errorResponse.ContentEncoding;
                    }
                    else
                        throw webEx;
                }
                if (encoding == null || encoding.Length < 1)
                    encoding = "UTF-8";

                rspReader = new StreamReader(rspStream, Encoding.GetEncoding(encoding));
                rspStr = rspReader.ReadToEnd();

 

posted @ 2026-02-02 10:46  Robot-Blog  阅读(4)  评论(0)    收藏  举报