一個簡易的Http請求轉發器

這兩天一直再看微信開發,臨時在個人電腦搭了個IIS服務器作微信開發,外網也能訪問了,關鍵是,調試太麻煩了!!服務器

我寫完代碼,要將代碼發佈到IIS才能接收微信消息,但是在這個過程當中,我不知道微信發過來的是什麼,出現Bug調試麻煩,微信

我得 找到是哪裏 出現Bug了,修改代碼再發布!微信開發

有沒有辦法讓我可以像平時那樣,設個斷點就好了?app

因而我就寫了一個簡易的Http請求轉發器this

原理是這樣:微信先請求個人IIS服務器,IIS服務器經過下面這個module 將請求 轉發 到 Vs 的 IIS Express,IIS Expressurl

再返回響應內容到IIs,IIs最後將消息發到微信spa

看代碼:調試

public class Transformer:IHttpModule
    {
        public void Dispose()
        {
            
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += context_BeginRequest;
        }

        /// <summary>
        /// 要將Http請求轉發 到 的 目標Url
        /// </summary>
        public Uri ToUrl
        {
            get
            {
                //從配置中讀取
                string toUrl = System.Configuration.ConfigurationManager.AppSettings["TransToURL"];
                //判斷Url是否/結尾
                if (!toUrl.EndsWith("/"))
                {
                    toUrl = toUrl + "/";
                }
                Uri uri=new Uri(toUrl);
                return uri;
            }
        }

        /// <summary>
        /// 目標UrlHost
        /// </summary>
        public string ToUrlHost
        {
            get
            {
                return ToUrl.Host;
            }
        }

        /// <summary>
        /// 目標Url 的端口
        /// </summary>
        public string ToPort
        {
            get
            {
                var result = Regex.Match(ToUrl.ToString(), @"^http://.+:(\d+)", RegexOptions.IgnoreCase);
                if (result.Groups.Count > 1)
                {
                    return result.Groups[1].Value;
                }
                else
                {
                    return "";
                }
            }
        }

        /// <summary>
        /// 客戶端直接請求的Url ,也就是 本 應用程序的 Url ,全部對該Url的請求都會被轉發到 目標Url
        /// </summary>
        public Uri FromUrl { get; set; }

        /// <summary>
        /// 本應用程序Url Host
        /// </summary>
        public string FromUrlHost
        {
            get
            {
               return FromUrl.Host;
            }
        }

        /// <summary>
        /// 本應用程序Url 端口
        /// </summary>
        public string FromPort
        {
            get
            {
                var result = Regex.Match(FromUrl.ToString(), @"^http://.+:(\d+)", RegexOptions.IgnoreCase);
                if (result.Groups.Count > 1)
                {
                    return result.Groups[1].Value;
                }
                else
                {
                    return "";
                }
            }
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            string toUrl = this.ToUrl.ToString();

            HttpApplication app = sender as HttpApplication;
            var respone = app.Response;
            var request = app.Request;

            //初始化 本應用程序 Url
            FromUrl=new Uri(request.Url.ToString());
            
            
            //獲取轉換目標後的Url
            //將請求報文中的 Url 替換爲 目標 Url
            string tempUrl = this.ReplaceHostAndPort(FromUrl.ToString(),TransType.TransTo);

            //建立 Http 請求 用於將 替換後 請求報文 發往 目標 Url
            HttpWebRequest hRequest = HttpWebRequest.CreateHttp(tempUrl);

            //設置請求頭
            this.SetRequestHead(hRequest, request);

            #region 設置特殊請求頭
            if (!string.IsNullOrEmpty(request.Headers["Accept"]))
            {
                hRequest.Accept = request.Headers["Accept"];
            }
            if (!string.IsNullOrEmpty(request.Headers["Connection"]))
            {
                string connection = request.Headers["Connection"];
                hRequest.KeepAlive =
                    string.Compare(connection, "keep-alive", StringComparison.CurrentCultureIgnoreCase) == 0;
           
            }
            if (!string.IsNullOrEmpty(request.Headers["Content-Type"]))
            {
                hRequest.ContentType = request.Headers["Content-Type"];
            }
            if (!string.IsNullOrEmpty(request.Headers["Expect"]))
            {
                hRequest.Expect = request.Headers["Expect"];
            }
            if (!string.IsNullOrEmpty(request.Headers["Date"]))
            {
                hRequest.Date = Convert.ToDateTime(request.Headers["Date"]);
            }
            if (!string.IsNullOrEmpty(request.Headers["Host"]))
            {
                hRequest.Host = this.ToUrlHost;
            }
            if (!string.IsNullOrEmpty(request.Headers["If-Modified-Since"]))
            {
                hRequest.IfModifiedSince =Convert.ToDateTime( request.Headers["If-Modified-Since"]);
            }
            if (!string.IsNullOrEmpty(request.Headers["Referer"]))
            {
                hRequest.Referer = this.ReplaceHostAndPort(request.Headers["Referer"],TransType.TransTo);
            }
            if (!string.IsNullOrEmpty(request.Headers["User-Agent"]))
            {
                hRequest.UserAgent = request.Headers["User-Agent"];
            }
            if (!string.IsNullOrEmpty(request.Headers["Content-Length"]))
            {
                hRequest.ContentLength =Convert.ToInt32( request.Headers["Content-Length"]);
            }
            #endregion

            //判斷是不是Get請求,若是不是Get就寫入請求報文體
            if (String.Compare(request.HttpMethod, "get", StringComparison.CurrentCultureIgnoreCase) != 0)
            {
                //設置請求體
                this.SetRequestBody(hRequest, request);
            }

            //獲取響應報文
            WebResponse hRespone=null;
            try
            {
               hRespone= hRequest.GetResponse();
            }
            catch (Exception exp)
            {

                respone.Write(exp.Message);
                respone.End();
            }
            

            //設置響應頭
            this.SetResponeHead(hRespone, respone);

            #region 設置特殊響應頭
            if (!string.IsNullOrEmpty(hRespone.Headers["Content-Type"]))
            {
                respone.ContentType = hRespone.Headers["Content-Type"];
            }
            if (!string.IsNullOrEmpty(hRespone.Headers["Host"]))
            {
                respone.AddHeader("Host", FromUrlHost); 
            }
            if (!string.IsNullOrEmpty(hRespone.Headers["Referer"]))
            {
                respone.AddHeader("Referer",this.ReplaceHostAndPort(hRespone.Headers["Referer"], TransType.TransBack)); 
            }

            #endregion

            //寫入響應內容
            this.SetResponeBody(hRespone,respone);

            respone.End();
        }

        /// <summary>
        /// 設置請求頭
        /// </summary>
        /// <param name="nrq"></param>
        /// <param name="orq"></param>
        private void SetRequestHead(WebRequest nrq, HttpRequest orq)
        {
            foreach (var key in orq.Headers.AllKeys)
            {
                try
                {
                    nrq.Headers.Add(key, orq.Headers[key]);
                }
                catch (Exception)
                {
                    
                    continue;
                }
                
            }
        }


        /// <summary>
        /// 設置請求 報文體
        /// </summary>
        /// <param name="nrq"></param>
        /// <param name="orq"></param>
        private void SetRequestBody(WebRequest nrq, HttpRequest orq)
        {
            nrq.Method = "POST";
            var nStream = nrq.GetRequestStream();
            byte[] buffer = new byte[1024 * 2];
            int rLength = 0;
            do
            {
                rLength = orq.InputStream.Read(buffer, 0, buffer.Length);
                nStream.Write(buffer, 0, rLength);
            } while (rLength > 0);
        }

        /// <summary>
        /// 設置響應頭
        /// </summary>
        /// <param name="nrp"></param>
        /// <param name="orp"></param>
        private void SetResponeHead(WebResponse nrp, HttpResponse orp)
        {
            foreach (var key in nrp.Headers.AllKeys)
            {
                try
                {
                    orp.Headers.Add(key, nrp.Headers[key]);
                }
                catch (Exception)
                {
                    
                    continue;
                }
               
            }
        }

        /// <summary>
        /// 設置響應報文體
        /// </summary>
        /// <param name="nrp"></param>
        /// <param name="orp"></param>
        private void SetResponeBody(WebResponse nrp, HttpResponse orp)
        {
            var nStream = nrp.GetResponseStream();
            byte[] buffer = new byte[1024 * 2];
            int rLength = 0;
            do
            {
                rLength = nStream.Read(buffer, 0, buffer.Length);
                orp.OutputStream.Write(buffer, 0, rLength);
            } while (rLength > 0);
        }

        /// <summary>
        /// 替換 Host和Port
        /// </summary>
        /// <param name="url"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private string ReplaceHostAndPort(string url, TransType type)
        {
            string tempToPortStr = string.IsNullOrEmpty(ToPort) ? "" : ":" + ToPort;
            string tempFromPortStr = string.IsNullOrEmpty(FromPort) ? "" : ":" + FromPort;
            if (type==TransType.TransBack)
            {
                return url.Replace(ToUrlHost + tempToPortStr, FromUrlHost + tempFromPortStr);
            }
            else
            {
                return url.Replace(FromUrlHost + tempFromPortStr, ToUrlHost + tempToPortStr);
            }
        }
    }

    public enum TransType
    {
        TransTo,
        TransBack
    }
相關文章
相關標籤/搜索