这两天一直再看微信开发,临时在我的电脑搭了个IIS服务器做微信开发,外网也能访问了,关键是,调试太麻烦了!!

我写完代码,要将代码发布到IIS才能接收微信消息,可是在这个过程中,我不知道微信发过来的是什么,出现Bug调试麻烦,

我得 找到是哪里 出现Bug了,修改代码再发布!

有没有办法让我能够像平时那样,设个断点就行了?

于是我就写了一个简易的Http请求转发器

原理是这样:微信先请求我的IIS服务器,IIS服务器通过下面这个module 将请求 转发 到 Vs 的 IIS Express,IIS Express

再返回响应内容到IIs,IIs最后将消息发到微信

看代码:

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
}

一个简易的Http请求转发器的更多相关文章

  1. .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”

    FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...

  2. 探秘Tomcat——一个简易的Servlet容器

    即便再简陋的服务器也是服务器,今天就来循着书本的第二章来看看如何实现一个servlet容器. 背景知识 既然说到servlet容器这个名词,我们首先要了解它到底是什么. servlet 相比你或多或少 ...

  3. [后端人员耍前端系列]AngularJs篇:使用AngularJs打造一个简易权限系统

    一.引言 上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中.本篇博文将使用AngularJS来打造一个简易的权限管理系统.下面不多 ...

  4. ENode 2.0 - 第一个真实案例剖析-一个简易论坛(Forum)

    前言 经过不断的坚持和努力,ENode 2.0的第一个真实案例终于出来了.这个案例是一个简易的论坛,开发这个论坛的初衷是为了验证用ENode框架来开发一个真实项目的可行性.目前这个论坛在UI上是使用了 ...

  5. C 实现一个简易的Http服务器

    引言 做一个老实人挺好的,至少还觉得自己挺老实的. 再分享一首 自己喜欢的诗人的一首 情景诗. 每个人总会有问题,至少喜欢就好, 本文 参照 http 协议   http://www.cnblogs. ...

  6. AngularJs打造一个简易权限系统

    AngularJs打造一个简易权限系统 一.引言 上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中.本篇博文将使用AngularJ ...

  7. Tinywebserver:一个简易的web服务器

    这是学习网络编程后写的一个练手的小程序,可以帮助复习I/O模型,epoll使用,线程池,HTTP协议等内容. 程序代码是基于<Linux高性能服务器编程>一书编写的. 首先回顾程序中的核心 ...

  8. 使用 RxJS 实现一个简易的仿 Elm 架构应用

    使用 RxJS 实现一个简易的仿 Elm 架构应用 标签(空格分隔): 前端 什么是 Elm 架构 Elm 架构是一种使用 Elm 语言编写 Web 前端应用的简单架构,在代码模块化.代码重用以及测试 ...

  9. day-1 用python编写一个简易的FTP服务器

    从某宝上购买了一份<Python神经网络深度学习>课程,按照视频教程,用python语言,写了一个简易的FTP服务端和客户端程序,以前也用C++写过聊天程序,编程思路差不多,但是pytho ...

随机推荐

  1. defaultdict & Counter

    在使用python原生的数据结构dict的时候,如果d[key]这样的方式访问,当指定的key不存在时,会抛出keyError异常.但是如果使用defaultdict(导入collections),只 ...

  2. BZOJ_5418_[Noi2018]屠龙勇士_exgcd+excrt

    BZOJ_5418_[Noi2018]屠龙勇士_exgcd+excrt Description www.lydsy.com/JudgeOnline/upload/noi2018day2.pdf 每次用 ...

  3. webpack 小demo

    1 安装node.js 2 安装cnpm 3 安装webpack cnpm install --save-dev webpack 对于大多数项目,我们建议本地安装.这可以使我们在引入破坏式变更的依赖时 ...

  4. Nhibernate中多Or条件的查询,很多Or的查询

    public IList<object[]> GetRequestAllByUserCodeUnitSysClassify1(string unitNo, string system, s ...

  5. json对象和json数组

    json字符串对象和json字符串数组:JSONArray跟JSONObject的区别就是JSONArray比JSONObject多中括号[] jsonObject: "Row": ...

  6. python 之元类

    定义类的两种方法: 1.class定义 2.type(类名,类的基类们,类的名称空间) # 定义类的三要素:类名.基类.名称空间 class_name = 'Chinese' class_bases ...

  7. 【eclipse插件开发实战】Eclipse插件开发2——SWT

    Eclipse插件开发实战2--SWT 一.SWT简介 SWT(StandardWidget Toolkit) 标准小窗口工具箱,一开源的GUI编程框架,与AWT/Swing有相似的用处,eclips ...

  8. PHP实现人脸识别技术

    这次人脸识别技术,是实现在微信端的,也就是说利用公众微信平台,调用第三的API来实现人脸识别这项技术的. 实现的思路: 首先呢,将收集的照片,建立一个照片库,然后利用在微信平台发送的照片,去到照片库进 ...

  9. CodeForces - 377A Maze BFS逆思维

    Maze Pavel loves grid mazes. A grid maze is an n × m rectangle maze where each cell is either empty, ...

  10. C#项目中一些文件类型说明

    designer.cs  是窗体设计器生成的代码文件,作用是对窗体上的控件做初始化工作 (在函数InitializeComponent()中)VS2003以前都把这部分代码放到窗体的cs文件中,由于这 ...