增加对象池StringBuilderPool,减少对象分配
大石头 authored at 2018-06-12 14:28:17
4.50 KiB
X
using System;
using System.Text;
using NewLife.Collections;

namespace NewLife.Http
{
    /// <summary>Http请求</summary>
    public class HttpRequest : HttpBase
    {
        #region 属性
        /// <summary>Http方法</summary>
        public String Method { get; set; }

        /// <summary>资源路径</summary>
        public Uri Url { get; set; }

        /// <summary>用户代理</summary>
        public String UserAgent { get; set; }

        /// <summary>是否压缩</summary>
        public Boolean Compressed { get; set; }

        /// <summary>保持连接</summary>
        public Boolean KeepAlive { get; set; }

        /// <summary>可接受内容</summary>
        public String Accept { get; set; }

        /// <summary>接受语言</summary>
        public String AcceptLanguage { get; set; }

        /// <summary>引用路径</summary>
        public String Referer { get; set; }
        #endregion

        /// <summary>分析第一行</summary>
        /// <param name="firstLine"></param>
        protected override Boolean OnParse(String firstLine)
        {
            if (firstLine.IsNullOrEmpty()) return false;

            var ss = firstLine.Split(" ");
            if (ss.Length < 3) return false;

            // 分析请求方法 GET / HTTP/1.1
            if (ss.Length >= 3 && ss[2].StartsWithIgnoreCase("HTTP/"))
            {
                Method = ss[0];

                // 构造资源路径
                var sch = Headers["Sec-WebSocket-Key"] + "" != "" ? "ws" : "http";
                var host = Headers["Host"] + "";
                var uri = "{0}://{1}".F(sch, host);
                //var uri = "{0}://{1}".F(IsSSL ? "https" : "http", host);
                //if (host.IsNullOrEmpty() || !host.Contains(":"))
                //{
                //    var port = Local.Port;
                //    if (IsSSL && port != 443 || !IsSSL && port != 80) uri += ":" + port;
                //}
                uri += ss[1];
                Url = new Uri(uri);
            }

            UserAgent = Headers["User-Agent"] + "";
            Compressed = (Headers["Accept-Encoding"] + "").Contains("deflate");
            KeepAlive = (Headers["Connection"] + "").EqualIgnoreCase("keep-alive");
            Accept = Headers["Accept"] + "";
            AcceptLanguage = Headers["Accept-Language"] + "";
            Referer = Headers["Referer"] + "";

            return true;
        }

        /// <summary>创建头部</summary>
        /// <param name="length"></param>
        /// <returns></returns>
        protected override String BuildHeader(Int32 length)
        {
            if (Method.IsNullOrEmpty()) Method = length > 0 ? "POST" : "GET";

            // 分解主机和资源
            var host = "";
            var uri = Url;
            if (uri == null) uri = new Uri("/");

            if (uri.Scheme.EqualIgnoreCase("http", "ws"))
            {
                if (uri.Port == 80)
                    host = uri.Host;
                else
                    host = "{0}:{1}".F(uri.Host, uri.Port);
            }
            else if (uri.Scheme.EqualIgnoreCase("https"))
            {
                if (uri.Port == 443)
                    host = uri.Host;
                else
                    host = "{0}:{1}".F(uri.Host, uri.Port);
            }

            // 构建头部
            var sb = Pool.StringBuilder.Get();
            sb.AppendFormat("{0} {1} HTTP/1.1\r\n", Method, uri.PathAndQuery);
            sb.AppendFormat("Host:{0}\r\n", host);

            if (!Accept.IsNullOrEmpty()) sb.AppendFormat("Accept:{0}\r\n", Accept);
            if (Compressed) sb.AppendLine("Accept-Encoding:gzip, deflate");
            if (!AcceptLanguage.IsNullOrEmpty()) sb.AppendFormat("AcceptLanguage:{0}\r\n", AcceptLanguage);
            if (!UserAgent.IsNullOrEmpty()) sb.AppendFormat("User-Agent:{0}\r\n", UserAgent);

            // 内容长度
            if (length > 0) sb.AppendFormat("Content-Length:{0}\r\n", length);
            if (!ContentType.IsNullOrEmpty()) sb.AppendFormat("Content-Type:{0}\r\n", ContentType);

            if (KeepAlive) sb.AppendLine("Connection:keep-alive");
            if (!Referer.IsNullOrEmpty()) sb.AppendFormat("Referer:{0}\r\n", Referer);

            foreach (var item in Headers)
            {
                sb.AppendFormat("{0}:{1}\r\n", item.Key, item.Value);
            }

            sb.AppendLine();

            return sb.Put(true);
        }
    }
}