C# Http请求封装(携带cookie版)(用于模拟登录)

C# 2466次浏览 本站
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;

namespace RC.Software.Travel
{
    public class HttpHelper
    {
        private static readonly HashSet<string> Unchangeheads = new HashSet<string>();

        /// <summary>
        ///     默认的头
        /// </summary>
        public static string defaultHeaders =
            @"Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Pragma:no-cache
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36";

        /// <summary>
        ///     平均相应时间
        /// </summary>
        private long avgResponseMilliseconds = -1;

        /// <summary>
        ///     cookies 字典
        /// </summary>
        private readonly Dictionary<string, Cookie> cookieDic = new Dictionary<string, Cookie>();

        /// <summary>
        ///     是否跟踪cookies
        /// </summary>
        private readonly bool isTrackCookies;

        static HttpHelper()
        {
            Unchangeheads.Add("Host");
            Unchangeheads.Add("Connection");
            Unchangeheads.Add("User-Agent");
            Unchangeheads.Add("Referer");
            Unchangeheads.Add("Range");
            Unchangeheads.Add("Content-Type");
            Unchangeheads.Add("Content-Length");
            Unchangeheads.Add("Expect");
            Unchangeheads.Add("Proxy-Connection");
            Unchangeheads.Add("If-Modified-Since");
            Unchangeheads.Add("Keep-alive");
            Unchangeheads.Add("Accept");
            ServicePointManager.DefaultConnectionLimit = 1000; //最大连接数
        }

        public HttpHelper(bool isTrackCookies = false)
        {
            this.isTrackCookies = isTrackCookies;
        }

        /// <summary>
        ///     平均相应时间
        /// </summary>
        public long AvgResponseMilliseconds
        {
            get { return avgResponseMilliseconds; }

            set
            {
                if (avgResponseMilliseconds != -1)
                    avgResponseMilliseconds = value + avgResponseMilliseconds / 2;
                else
                    avgResponseMilliseconds = value;
            }
        }

        /// <summary>
        ///     http请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="method">POST,GET</param>
        /// <param name="headers">http的头部,直接拷贝谷歌请求的头部即可</param>
        /// <param name="content">content,每个key,value 都要UrlEncode才行</param>
        /// <param name="contentEncode">content的编码</param>
        /// <param name="proxyUrl">代理url</param>
        /// <returns></returns>
        public string Http(string url, string method, string headers, string content, Encoding contentEncode,
            string proxyUrl = "")
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;
            if (method.Equals("GET", StringComparison.InvariantCultureIgnoreCase))
            {
                request.MaximumAutomaticRedirections = 100;
                request.AllowAutoRedirect = false;
            }

            FillHeaders(request, headers);
            FillProxy(request, proxyUrl);

            #region 添加Post 参数

            if (contentEncode == null) contentEncode = Encoding.UTF8;
            if (!string.IsNullOrWhiteSpace(content))
            {
                var data = contentEncode.GetBytes(content);
                request.ContentLength = data.Length;
                using (var reqStream = request.GetRequestStream())
                {
                    reqStream.Write(data, 0, data.Length);
                    reqStream.Close();
                }
            }

            #endregion

            HttpWebResponse response = null;
            var sw = new Stopwatch();
            try
            {
                sw.Start();
                response = (HttpWebResponse)request.GetResponse();
                sw.Stop();
                AvgResponseMilliseconds = sw.ElapsedMilliseconds;
                var cc = new CookieCollection();
                var cookieString = response.Headers[HttpResponseHeader.SetCookie];
                if (!string.IsNullOrWhiteSpace(cookieString))
                {
                    var spilit = cookieString.Split(';');
                    foreach (var item in spilit)
                    {
                        var kv = item.Split('=');
                        if (kv.Length == 2)
                            cc.Add(new Cookie(kv[0].Trim(), kv[1].Trim()));
                    }
                }

                TrackCookies(cc);
            }
            catch (Exception ex)
            {
                sw.Stop();
                AvgResponseMilliseconds = sw.ElapsedMilliseconds;
                return "";
            }

            var result = getResponseBody(response);
            return result;
        }


        /// <summary>
        ///     post 请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="content"></param>
        /// <param name="contentEncode"></param>
        /// <param name="proxyUrl"></param>
        /// <returns></returns>
        public string HttpPost(string url, string headers, string content, Encoding contentEncode,string proxyUrl = null)
        {
            return Http(url, "POST", headers, content, contentEncode, proxyUrl);
        }

        /// <summary>
        ///     get 请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="content"></param>
        /// <param name="proxyUrl"></param>
        /// <returns></returns>
        public string HttpGet(string url, string headers, string content = null, string proxyUrl = null)
        {
            return Http(url, "GET", headers, null, null, proxyUrl);
        }

        /// <summary>
        ///     填充代理
        /// </summary>
        /// <param name="request"></param>
        /// <param name="proxyUri"></param>
        private void FillProxy(HttpWebRequest request, string proxyUri)
        {
            if (!string.IsNullOrWhiteSpace(proxyUri))
            {
                var proxy = new WebProxy();
                proxy.Address = new Uri(proxyUri);
                request.Proxy = proxy;
            }
        }


        /// <summary>
        ///     跟踪cookies
        /// </summary>
        /// <param name="cookies"></param>
        private void TrackCookies(CookieCollection cookies)
        {
            if (!isTrackCookies) return;
            if (cookies == null) return;
            foreach (Cookie c in cookies)
                if (cookieDic.ContainsKey(c.Name))
                    cookieDic[c.Name] = c;
                else
                    cookieDic.Add(c.Name, c);
        }

        /// <summary>
        ///     格式cookies
        /// </summary>
        private string GetCookieStr()
        {
            var sb = new StringBuilder();
            foreach (var item in cookieDic)
                if (!item.Value.Expired)
                {
                    if (sb.Length == 0)
                        sb.Append(item.Key).Append("=").Append(item.Value.Value);
                    else
                        sb.Append("; ").Append(item.Key).Append(" = ").Append(item.Value.Value);
                }

            return sb.ToString();
        }

        /// <summary>
        ///     填充头
        /// </summary>
        /// <param name="request"></param>
        /// <param name="headers"></param>
        /// <param name="isPrint"></param>
        private void FillHeaders(HttpWebRequest request, string headers, bool isPrint = false)
        {
            if (request == null) return;
            if (string.IsNullOrWhiteSpace(headers)) return;
            var hsplit = headers.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in hsplit)
            {
                var kv = item.Split(':');
                if (kv.Length == 2)
                {
                    var key = kv[0].Trim();
                    var value = string.Join(":", kv.Skip(1)).Trim();
                    if (!Unchangeheads.Contains(key))
                    {
                        request.Headers.Add(key, value);
                    }
                    else
                    {
                        #region  设置http头

                        switch (key)
                        {
                            case "Accept":
                                {
                                    request.Accept = value;
                                    break;
                                }
                            case "Host":
                                {
                                    request.Host = value;
                                    break;
                                }
                            case "Connection":
                                {
                                    if (value == "keep-alive")
                                        request.KeepAlive = true;
                                    else
                                        request.KeepAlive = false; //just test
                                    break;
                                }
                            case "Content-Type":
                                {
                                    request.ContentType = value;
                                    break;
                                }

                            case "User-Agent":
                                {
                                    request.UserAgent = value;
                                    break;
                                }
                            case "Referer":
                                {
                                    request.Referer = value;
                                    break;
                                }

                            case "Content-Length":
                                {
                                    request.ContentLength = Convert.ToInt64(value);
                                    break;
                                }
                            case "Expect":
                                {
                                    request.Expect = value;
                                    break;
                                }
                            case "If-Modified-Since":
                                {
                                    request.IfModifiedSince = Convert.ToDateTime(value);
                                    break;
                                }
                        }

                        #endregion
                    }
                }
            }

            var cc = new CookieCollection();
            var cookieString = request.Headers[HttpRequestHeader.Cookie];
            if (!string.IsNullOrWhiteSpace(cookieString))
            {
                var spilit = cookieString.Split(';');
                foreach (var item in spilit)
                {
                    var kv = item.Split('=');
                    if (kv.Length == 2)
                        cc.Add(new Cookie(kv[0].Trim(), kv[1].Trim()));
                }
            }

            TrackCookies(cc);
            if (!isTrackCookies)
                request.Headers[HttpRequestHeader.Cookie] = "";
            else
                request.Headers[HttpRequestHeader.Cookie] = GetCookieStr();

            #region 打印头

            if (isPrint)
                for (var i = 0; i < request.Headers.AllKeys.Length; i++)
                {
                    var key = request.Headers.AllKeys[i];
                    Console.WriteLine(key + ":" + request.Headers[key]);
                }

            #endregion
        }


        /// <summary>
        ///     打印ResponseHeaders
        /// </summary>
        /// <param name="response"></param>
        private void PrintResponseHeaders(HttpWebResponse response)
        {
            #region 打印头

            if (response == null) return;
            for (var i = 0; i < response.Headers.AllKeys.Length; i++)
            {
                var key = response.Headers.AllKeys[i];
                Console.WriteLine(key + ":" + response.Headers[key]);
            }

            #endregion
        }


        /// <summary>
        ///     返回body内容
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        private string getResponseBody(HttpWebResponse response)
        {
            var defaultEncode = Encoding.UTF8;
            var contentType = response.ContentType;
            if (contentType.ToLower().Contains("gb2312"))
                defaultEncode = Encoding.GetEncoding("gb2312");
            else if (contentType.ToLower().Contains("gbk"))
                defaultEncode = Encoding.GetEncoding("gbk");
            else if (contentType.ToLower().Contains("zh-cn")) defaultEncode = Encoding.GetEncoding("zh-cn");

            string responseBody;
            if (response.ContentEncoding.ToLower().Contains("gzip"))
                using (var stream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress))
                {
                    using (var reader = new StreamReader(stream))
                    {
                        responseBody = reader.ReadToEnd();
                    }
                }
            else if (response.ContentEncoding.ToLower().Contains("deflate"))
                using (var stream = new DeflateStream(response.GetResponseStream(), CompressionMode.Decompress))
                {
                    using (var reader = new StreamReader(stream, defaultEncode))
                    {
                        responseBody = reader.ReadToEnd();
                    }
                }
            else
                using (var stream = response.GetResponseStream())
                {
                    using (var reader = new StreamReader(stream, defaultEncode))
                    {
                        responseBody = reader.ReadToEnd();
                    }
                }

            return responseBody;
        }


        public static string UrlEncode(string item, Encoding code)
        {
            return HttpUtility.UrlEncode(item.Trim('\t').Trim(), Encoding.GetEncoding("gb2312"));
        }

        public static string UrlEncodeByGB2312(string item)
        {
            return UrlEncode(item, Encoding.GetEncoding("gb2312"));
        }


        public static string UrlEncodeByUTF8(string item)
        {
            return UrlEncode(item, Encoding.GetEncoding("utf-8"));
        }

        public static string HtmlDecode(string item)
        {
            return WebUtility.HtmlDecode(item.Trim('\t').Trim());
        }

        public Res HttpReq(string url, string method, string headers, string content, Encoding contentEncode,string proxyUrl = "")
        {
            var res = new Res();
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;
            if (method.Equals("GET", StringComparison.InvariantCultureIgnoreCase))
            {
                request.MaximumAutomaticRedirections = 100;
                request.AllowAutoRedirect = false;
            }

            FillHeaders(request, headers);
            FillProxy(request, proxyUrl);

            #region 添加Post 参数

            if (method.Equals("POST", StringComparison.InvariantCultureIgnoreCase))
            {
                if (contentEncode == null) contentEncode = Encoding.UTF8;
                if (!string.IsNullOrWhiteSpace(content))
                {
                    var data = contentEncode.GetBytes(content);
                    request.ContentLength = data.Length;
                    using (var reqStream = request.GetRequestStream())
                    {
                        reqStream.Write(data, 0, data.Length);
                        reqStream.Close();
                    }
                }
            }

            #endregion

            HttpWebResponse response = null;
            var sw = new Stopwatch();
            try
            {
                sw.Start();
                response = (HttpWebResponse)request.GetResponse();
                sw.Stop();
                AvgResponseMilliseconds = sw.ElapsedMilliseconds;
                var cc = new CookieCollection();
                var cookieString = response.Headers[HttpResponseHeader.SetCookie];
                res.Header = response.Headers.ToString();
                res.Cookie = cookieString;
                if (!string.IsNullOrWhiteSpace(cookieString))
                {
                    var spilit = cookieString.Split(';');
                    foreach (var item in spilit)
                    {
                        var kv = item.Split('=');
                        if (kv.Length == 2)
                            cc.Add(new Cookie(kv[0].Trim().Replace("HttpOnly,",""), kv[1].Trim()));
                    }
                }

                TrackCookies(cc);
            }
            catch (Exception ex)
            {
                sw.Stop();
                AvgResponseMilliseconds = sw.ElapsedMilliseconds;
                res.Body = ex.Message;
                return res;
            }

            var result = getResponseBody(response);
            res.Body = result;
            return res;
        }

    }

}
            

发表评论

电子邮件地址不会被公开。 必填项已用*标注