这两天一直再看微信开发,临时在我的电脑搭了个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. codeforces 669A A. Little Artem and Presents(水题)

    题目链接: A. Little Artem and Presents time limit per test 2 seconds memory limit per test 256 megabytes ...

  2. Logcat不显示Application的解决办法

    Window - show view - devices - debug ----2014.12.1------ 只有在DDMS的device中显示进程名,logcat中的Application标签才 ...

  3. vim 使用、设置笔记

    一.设置.vimrc( windows下通常为_vimrc) 1.设置vim中tab的缩进 set ts=4  (注:ts是tabstop的缩写,设TAB宽4个空格) set expandtab (注 ...

  4. sipp 对asterisk 进行压力测试

    测试环境 asterisk  192.168.106.170 版本astrisk1.8 sipp   192.168.106.141 sipp版本3.3 安装依赖包yum install make g ...

  5. AutoIT:界面与自动化操作结合来简化日常劳动: .Net Reactor验证License,设置License,创建License,截图AutoIt自动化实现。(七)

    版本六中存在一个显著问题是: 当exe文件生存之后,运行的时候,通过consoleWrite函数打印出来的数据是无法展示出来的.这就存在一个问题:当运行失败的时候,我还是看不到任何log信息. 于是, ...

  6. Python下使用Psyco模块优化运行速度

    今天介绍下Psyco模块,Psyco模块可以使你的Python程序运行的像C语言一样快.都说Python语言易用易学,但性能上跟一些编译语言(如C语言)比较要差不少,这里可以用C语言和Python语言 ...

  7. Ubuntu 安装mysql和 简单命令操作

    ubuntu上安装mysql非常简单只需要几条命令就可以完成. 1. sudo apt-get install mysql-server   2. apt-get isntall mysql-clie ...

  8. Windows服务卸载服务窗口仍显示的问题

    关于Windows服务通过命令卸载后, 打开服务窗口,服务还有显示,只是状态改为了禁用,运行停止.那么我们怎么解决呢, 不要心慌,打开你的任务管理器,查看服务所用的exe程序是否还在运行,若有的话,便 ...

  9. ubuntu_ root change to user

    (1)从user用户切换到root用户 不管是用图形模式登录Ubuntu,还是命令行模式登录,我们会发现缺省的用户是user 但是当我们需要执行一些具有root权限的操作(如修还系统文件)时,经常需要 ...

  10. PXE与cobbler实现系统自动安装

    安装操作系统的流程事实上并不复杂,如果你要给三五台服务器安装系统那么我们手工去安装即可.但是当我们要部署的是大型机房的操作系统的时候显然手动安装去一台一台的点,是不现实的.尤其现在互联网行业高速发展, ...