這兩天一直再看微信開發,臨時在個人電腦搭了個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 }