模擬實現ASP.NET框架的基本功能(二)


namespace 小型IIS服務器

{
    /// <summary>
    /// 管理用戶向服務器發送的請求報文數據 
    /// 報文行
    /// 報文頭
    /// 空白行
    /// 報文體
    /// </summary>
    public class HttpRequest
    {
        /*
         * 00 有參構造函數 傳入用戶請求報文數據 實例化爲用請求報文創建的相關屬性
         * 01 解析用戶請求報文數據 創建相應的屬性存儲用戶請求報文數據 報文數據可以分爲幾個部分 分別存儲
         * 02 將用戶請求報文分解 給相應創建的屬性賦值 
         */
        #region 0.0 構造函數
        private string requestMsg;


        public HttpRequest() { }
        public HttpRequest(string requestMsg)
        {
            this.requestMsg = requestMsg;
            //調用解析請求報文方法,分解請求報文,並給相關屬性賦值
            InitAttr(this.requestMsg);
        }
        #endregion

        #region 1.0 請求報文由多個部分組成 創建相應的屬性來存儲

        private string httpMethod;
        /// <summary>
        /// Http請求方法(get,post)
        /// </summary>
        public string HttpMethod
        {
            get { return httpMethod; }
            set { httpMethod = value; }

        }

        private string rawUrl;

        /// <summary>
        /// 請求報文的虛擬路徑  /index.html
        /// </summary>
        public string RawUrl
        {
            get { return rawUrl; }
            set { rawUrl = value; }

        }

        private string httpVerb;

        /// <summary>
        /// Http協議  HTTP/1.1
        /// </summary>
        public string HttpVerb
        {
            get { return httpVerb; }
            set { httpVerb = value; }
        }

        private string urlExtention;
        /// <summary>
        /// 請求報文URL的後綴名 (例如:.html,.js,.css,.aspx.....)
        /// </summary>
        public string UrlExtention
        {
            get { return urlExtention; }
            set { urlExtention = value; }
        }
        #endregion

        #region 2.0 將請求報文中相應的部分 解析成相應的屬性部分 並賦值

        /// <summary>
        /// 將請求報文中相應的部分 解析成相應的屬性部分 並賦值
        /// </summary>
        /// <param name="requestMsg"></param>
        private void InitAttr(string requestMsg)
        {
            //如果請求報文爲空,則不處理
            if (string.IsNullOrEmpty(requestMsg))
            {
                return;
            }

            //01 將請求報文文本數據以 \r\n分隔 用數組存儲
            string[] requestArr = requestMsg.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

            //02 提取數組中的數據 根據 空格 分隔
            if (requestArr.Length > 0)
            {
                string requestLine = requestArr[0];     //  GET /index.html HTTP/1.1 \r\n
                string[] lineArr = requestLine.Split(' ');
                if (lineArr.Length == 3)
                {
                    httpMethod = lineArr[0];
                    rawUrl = lineArr[1];
                    httpVerb = lineArr[2];
                    this.urlExtention = System.IO.Path.GetExtension(RawUrl);
                }
            }
        }
        #endregion
    }

}


//2.0 

namespace 小型IIS服務器
{
    /// <summary>
    /// 管理服務器響應報文 將響應報文組成 
    /// 響應報文行
    /// 響應報文頭
    /// 空白行
    /// 響應報文體
    /// </summary>
    public class HttpResponse
    {
        /*
         * 00 構造函數 在有參構造函數中傳入 【處理用戶請求報文的對象(HttpRequeset的對象)】 以獲取用戶請求報文中相應的屬性
         *              給狀態碼賦值
         * 01 狀態碼的設置 響應報文中有表示響應報文狀態的狀態碼 需要根據標準 自己設置 用字典結構存儲 一個狀態碼對應着一個解釋
         * 02 報文段的設置 獲取報文段的長度 創建報文段對象 以給報文段賦值
         * 03 組裝響應報文 用 StringBuilder 存儲 ;AppendLine整行添加
         *      可以將響應報文大致分爲兩個部分,一部分:響應報文行 + 響應報文頭 + 空白行  一部分:響應報文體
         *      兩部分分別用byte[]數組存儲,最後用byte[]數組合並,返回響應報文      
         */
        #region 0.0 構造函數

        private HttpRequest request;

        public HttpResponse() { }

        public HttpResponse(HttpRequest request)
        {
            this.request = request;
            //設置狀態碼
            stateDic.Add(200, "OK");
            stateDic.Add(404, "File Not Found");
            stateDic.Add(500, "Internal Server Error");
        } 
        #endregion

        #region 1.0 設置狀態碼
        /// <summary>
        /// 存儲狀態碼 一個狀態碼 有對應的解釋
        /// </summary>
        Dictionary<int, string> stateDic = new Dictionary<int, string>();

        int stateCode = 200;
        /// <summary>
        /// 響應狀態碼
        /// </summary>
        public int StateCode
        {
            get { return stateCode; }
            set { stateCode = value; }
        }

        string stataString;
        /// <summary>
        /// 響應狀態碼對應的解釋字符串
        /// </summary>
        public string StataString
        {
            get { return stateDic[StateCode]; }
        }

        #endregion

        #region 2.0 報文段屬性設置 

        int contentLength;
        /// <summary>
        /// 報文長度
        /// </summary>
        public int ContentLength
        {
            get { return ContentBody.Length; }
        }
        byte[] contentBody = new byte[0];
        /// <summary>
        /// 儲存相應報文體的字符數組
        /// </summary>
        public byte[] ContentBody
        {
            get { return contentBody; }
            set { contentBody = value; }
        }

        StringBuilder contentBodyStr = new StringBuilder(500);
        /// <summary>
        /// 提供給外部方法調用的方法,將響應報文體的數據存儲到contentBody中
        /// </summary>
        /// <param name="contentBody"></param>
        public void Write(string contentBody)
        {
            //用StringBuilder存儲響應報文體,然後將其轉變爲byte[]數據流類型賦值給ContentBody
            contentBodyStr.Append(contentBody);
            //將字符串轉爲byte[]數組數據
            ContentBody = Encoding.UTF8.GetBytes(contentBodyStr.ToString());
        }
        
        #endregion

        #region 3.0 組成響應報文 +byte[] GetResponseMessage()

        /// <summary>
        /// 組裝響應報文
        /// </summary>
        /// <returns></returns>
        public byte[] GetResponseMessage()
        {
            System.Text.StringBuilder lineHead = new StringBuilder();
            //01 組裝響應 報文行 HTTP/1.1 200 OK
            lineHead.AppendLine(request.HttpVerb + " " + StateCode + " " + StataString);
            //02 組裝響應 報文頭 Content-Type: text/html;charset=utf-8
            lineHead.AppendLine("Content-Type: text/html;charset=utf-8");
            //Content-Length: 325
            lineHead.AppendLine("Content-Length: " + ContentLength);
            //Server: Mini IIS
            lineHead.AppendLine("Server: Mini IIS");

            //03 組裝響應 空白行
            lineHead.AppendLine("");
            //04 組裝響應 報文體
            //將響應報文頭轉換爲byte[]數組
            byte[] headByte = System.Text.Encoding.UTF8.GetBytes(lineHead.ToString());

            //響應報文長度
            byte[] responseByte = new byte[headByte.Length + ContentLength];

            //將headByte 與 報文體合併
            headByte.CopyTo(responseByte, 0);
            ContentBody.CopyTo(responseByte, headByte.Length);

            //05 返回響應報文
            return responseByte;
        }
        #endregion
    }
}


//3.0 HttpServerUtility

namespace 小型IIS服務器
{
    /// <summary>
    /// 幫助類
    /// </summary>
    public class HttpServerUtility
    {
        /// <summary>
        /// 根據虛擬路徑獲取物理路徑
        /// </summary>
        /// <param name="virtualPath">虛擬路徑</param>
        public string MapPath(string virtualPath)
        {
            string basePath = AppDomain.CurrentDomain.BaseDirectory;
            return basePath + virtualPath;
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章