C#实现HTTP访问类HttpHelper的示例详解

.NET
438
0
0
2023-02-05
标签   C#

在项目开发过程中,我们经常会访问第三方接口,如我们需要接入的第三方接口是Web API,这时候我们就需要使用HttpHelper调用远程接口了。示例中的HttpHelper类使用Log4Net记录了每次调用的请求内容和响应内容的日志,并且每条日志都带上了链路ID和标识,这样方便我们在排查问题时能快速的找到当时的请求和响应内容,进而定位分析问题。大家在使用的时候如不需要记录日志,删除掉即可。

HttpHelper类代码如下:

public class HttpHelper : IDisposable
{
    private bool _disposable = false;
    /// <summary>
    /// 请求编码格式默认utf-8;
    /// </summary>
    public Encoding HtmlEncoding = Encoding.UTF8;
    /// <summary>
    /// 请求时间
    /// </summary>
    public int Timeout = 5000;
 
    public CookieContainer Cookies = null;
    /// <summary>
    /// 是否记录Cookies
    /// </summary>
    public bool IsRecordCookie = false;
 
    public string ContentType = "application/x-www-form-urlencoded";
 
    public string AcceptLanguage = "en-US, en; q=0.8, zh-Hans-CN; q=0.5, zh-Hans; q=0.3";
 
    public string KeepAlive = "Keep-Alive";
 
    public string Accept = "*/*";
 
    private const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240";
 
    private static ILogger Logger = Log4NetLoggerFactory.Instance.Create("remote.info");
 
    public HttpHelper()
    {
        //允许最大连接数,突破Http协议的并发连接数限制
        ServicePointManager.DefaultConnectionLimit = 512;
    }
 
    /// <summary>
    /// 上传图片
    /// </summary>
    /// <param name="url"></param>
    /// <param name="bArr"></param>
    /// <param name="fileName"></param>
    /// <returns></returns>
    public HttpRequestEntity RequestFile(string url, byte[] bArr, string fileName = "")
    {
        var result = new HttpRequestEntity { IsSuccess = 0 };
        //后续需要再放开,启用时需增加日志收集
        //if (string.IsNullOrEmpty(url))
        //    throw new ArgumentNullException("请求Url不能为空值");
 
        //if (bArr == null || bArr.Length <= 0)
        //    throw new AccessViolationException("缺少输入数据");
 
        //Stream requestStream = null;
        //StreamReader streamReader = null;
        //HttpWebResponse response = null;
        //HttpWebRequest request = null;
        //try
        //{
        //    request = WebRequest.Create(url) as HttpWebRequest;
        //    request.AllowAutoRedirect = true;
        //    request.Method = "POST";
        //    string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线
        //    request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary;
        //    byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
        //    byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
 
        //    if (string.IsNullOrEmpty(fileName))
        //        fileName = DateTime.Now.ToString("yyyyMMddHHmmss");
 
        //    //请求头部信息 
        //    StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\nContent-Type:application/octet-stream\r\n\r\n", fileName));
        //    byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString());
        //    request.Headers.Add("auth", fileName);
        //    Stream postStream = request.GetRequestStream();
        //    postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
        //    postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
        //    postStream.Write(bArr, 0, bArr.Length);
        //    postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
        //    postStream.Close();
        //    response = request.GetResponse() as HttpWebResponse;
        //    requestStream = response.GetResponseStream();
        //    if (response.StatusCode == HttpStatusCode.OK)
        //    {
        //        result.IsSuccess = 0;
        //        if (requestStream != null)
        //        {
        //            streamReader = new StreamReader(requestStream, HtmlEncoding);
        //            result.ResponseContent = streamReader.ReadToEnd();
        //        }
        //    }
        //}
        //catch (Exception ex)
        //{
        //    result.IsSuccess = 1;
        //    result.ResponseContent = ex.Message;
        //}
        //finally
        //{
        //    if (requestStream != null)
        //    {
        //        requestStream.Close();
        //        requestStream.Dispose();
        //    }
 
        //    if (streamReader != null)
        //    {
        //        streamReader.Close();
        //        streamReader.Dispose();
        //    }
 
        //    request.Abort();
        //    if (response != null)
        //        response.Close();
 
        //}
 
        return result;
    }
 
    /// <summary>
    /// 基本请求方法
    /// </summary>
    /// <param name="requestType">HTTP请求类型</param>
    /// <param name="url">请求的URL</param>
    /// <param name="requestData">请求参数</param>
		/// <param name="traceID">链路ID,方便查询日志</param>
		/// <param name="markType">请求标识,方便查询日志</param>
    /// <returns></returns>
    private HttpRequestEntity BaseRequest(RequestType requestType, string url, string requestData, string traceID,string markType)
    {
        var result = new HttpRequestEntity { IsSuccess = 0 };
 
        if (string.IsNullOrEmpty(url))
            throw new ArgumentNullException("请求Url不能为空值");
 
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        Dictionary<string, object> resultLog = new Dictionary<string, object>();//log对象
        resultLog.Add("logType", "remote");
        resultLog.Add("traceID", traceID);
        resultLog.Add("localIp", IpHelper.LocalIp);
        resultLog.Add("markType", markType);
        resultLog.Add("url", url);            
        resultLog.Add("requestContent", HttpUtility.UrlDecode(requestData, Encoding.UTF8));
        resultLog.Add("createTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
        StackTrace ss = new StackTrace(true);
        System.Reflection.MethodBase mb = ss.GetFrame(2).GetMethod();//0表示当前栈空间,1表示上一级的栈空间,依次类推
        resultLog.Add("className", mb.DeclaringType.FullName);
        resultLog.Add("methodName", mb.Name);
        HttpStatusCode statusCode = HttpStatusCode.OK;
 
        if (IsRecordCookie)
            Cookies = new CookieContainer();
        Stream requestStream = null;
        StreamReader streamReader = null;
 
        HttpWebRequest webRe = null;
        HttpWebResponse webPos = null;
        try
        {
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                webRe = WebRequest.Create(url) as HttpWebRequest;
                webRe.ProtocolVersion = HttpVersion.Version10;
            }
            else
            {
                webRe = (HttpWebRequest)WebRequest.Create(url);
            }
 
            webRe.Headers.Add("Accept-Language", AcceptLanguage);
            webRe.Headers.Add("Keep-Alive", KeepAlive);
            webRe.UserAgent = UserAgent;
            webRe.Accept = Accept;
            webRe.Timeout = Timeout;
            webRe.ReadWriteTimeout = Timeout;
            webRe.CookieContainer = Cookies;
 
            if (requestType == RequestType.Post)
            {
                webRe.ContentType = string.Format("{0}; {1}", ContentType, HtmlEncoding.BodyName);
                byte[] datas = HtmlEncoding.GetBytes(requestData);
                webRe.Method = "POST";
                webRe.ContentLength = datas.Length;
                webRe.MaximumResponseHeadersLength = -1;
                requestStream = webRe.GetRequestStream();
                requestStream.Write(datas, 0, datas.Length);
                requestStream.Flush();
                requestStream.Close();
            }
            else
                webRe.Method = "GET";
 
            webPos = (HttpWebResponse)webRe.GetResponse();
            resultLog.Add("requestType", webRe.Method);
            statusCode = webPos.StatusCode;
            result.ResponseLength = webPos.ContentLength;
            result.ResponseEncodingName = webPos.ContentEncoding;
 
            requestStream = webPos.GetResponseStream();
            if (webPos.StatusCode == HttpStatusCode.OK)
            {
                result.IsSuccess = 0;
 
                if (requestStream != null)
                {
                    streamReader = new StreamReader(requestStream, HtmlEncoding);
                    result.ResponseContent = streamReader.ReadToEnd();
                }
            }
        }
        catch (Exception ex)
        {
            result.IsSuccess = 1;
            result.ResponseContent = ex.Message;
        }
        finally
        {
            if (requestStream != null)
            {
                requestStream.Close();
                requestStream.Dispose();
            }
 
            if (streamReader != null)
            {
                streamReader.Close();
                streamReader.Dispose();
            }
 
            webRe.Abort();
            if (webPos != null)
                webPos.Close();
 
        }
        if (result.IsSuccess == 1)
        {
            resultLog.Add("status", HttpStatusCode.InternalServerError);
            resultLog.Add("success", false);
            resultLog.Add("responseContent", result.ResponseContent);
            stopwatch.Stop();
            resultLog.Add("elapseTime", stopwatch.Elapsed.TotalMilliseconds);
            string log = JsonConvert.SerializeObject(resultLog);
            Logger.Info(log);
            Logger.Error(log);
        }
        else
        {
            resultLog.Add("status", statusCode);
            resultLog.Add("success", true);
            resultLog.Add("responseContent", result.ResponseContent);
            stopwatch.Stop();
            resultLog.Add("elapseTime", stopwatch.Elapsed.TotalMilliseconds);
            string log = JsonConvert.SerializeObject(resultLog);
            Logger.Info(log);
        }
        return result;
    }
 
    private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
    {
        return true; //总是接受  
    }
 
    /// <summary>
    /// Get请求
    /// </summary>
    /// <param name="url">请求地址</param>
		/// <param name="traceID">链路ID,方便查询日志</param>
		/// <param name="markType">请求标识,方便查询日志</param>
    /// <returns></returns>
    public HttpRequestEntity Request(string url, string traceID, string markType)
    {
        return BaseRequest(RequestType.Get, url, string.Empty, traceID, markType);
    }
 
    /// <summary>
    /// Post请求
    /// </summary>
    /// <param name="url">请求地址Url</param>
    /// <param name="requestData">请求内容参数</param>
		/// <param name="traceID">链路ID,方便查询日志</param>
		/// <param name="markType">请求标识,方便查询日志</param>
    /// <returns></returns>
    public HttpRequestEntity Request(string url, string requestData, string traceID, string markType)
    {
        return BaseRequest(RequestType.Post, url, requestData, traceID, markType);
    }
 
    ~HttpHelper()
    {
        Dispose(false);
    }
 
    #region IDisposable 成员
 
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
 
    protected virtual void Dispose(bool disposing)
    {
        if (this._disposable)
            return;
 
        if (disposing)
        {
 
        }
 
        _disposable = true;
    }
 
    #endregion
}
 
/// <summary>
/// HttpHelper请求方式
/// </summary>
public enum RequestType
{
    /// <summary>
    /// Get请求
    /// </summary>
    Get,
    /// <summary>
    /// Post请求
    /// </summary>
    Post
}
 
/// <summary>
/// HttpHelper请求时返回实体
/// </summary>
public class HttpRequestEntity
{
    /// <summary>
    /// 请求是否成功 0-成功(返回Http状态码200) 1-失败(出现异常)
    /// </summary>
    public int IsSuccess { get; set; }
    /// <summary>
    /// 请求返回内容
    /// </summary>
    public string ResponseContent { get; set; }
    /// <summary>
    /// 请求返回内容长度
    /// </summary>
    public long ResponseLength { get; set; }
    /// <summary>
    /// 请求返回编码类型
    /// </summary>
    public string ResponseEncodingName { get; set; }
}

调用示例如下:

HttpHelper helper = new HttpHelper();
HttpRequestEntity response = helper.Request("需要访问的URL", "请求需要的参数", "访问链路ID", "访问标识");
if (response.IsSuccess != 0)
{
	//程序处理异常,请重试!
}
else
{
	//请求响应成功	
}