这两天一直再看微信开发,临时在我的电脑搭了个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. 谈谈javaScript

    谈谈javaScript  (杰我学习) 一. 什么是JavaScript       人们通常所说的JavaScript,其正式名称为ECMAScript.这个标准由ECMA组织发展和维护.ECMA ...

  2. calico在docker上的部署及验证

    1. 背景 以下的部署以五台服务器环境为例: 服务器1: hostname为etcdnode1, IP为192.168.56.100 服务器2: hostname为etcdnode2, IP为192. ...

  3. hadoop各组件安装(非专业人士,不定期更新)

    压缩包下载http://www.cnblogs.com/bfmq/p/6027202.html 1.zookeepermkdir /usr/local/hadooptar zxf /root/zook ...

  4. 用HTML 5打造斯诺克桌球俱乐部(1) – 51CTO.COM

    本文介绍了如何利用HTML5技术来打造一款非常酷的斯诺克桌球游戏,文章中详细地列… 查阅全文 ›

  5. Win10资源管理器中的库文件夹按照修改日期排序

    win7之后添加的库十分的好用,可以将下载,音乐,文档设置在我的电脑(win10叫此电脑)首页,快速进入. 我对文件夹设置了按照时间排序,这样进去就可以直接看到最近下载了什么文件.但是win10用时间 ...

  6. Java中next() 与 nextLine() 区别

    next(): 1.一定要读取到有效字符后才可以结束输入. 2.对输入有效字符之前遇到的空白,next() 方法会自动将其去掉. 3.只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符. 4. ...

  7. Linux中如何开启8080端口供外界访问 和开启允许对外访问的端口8000

    举例: 开放10000端口的解决步骤如下: 1.修改/etc/sysconfig/iptables文件,增加如下一行: -A INPUT -m state --state NEW -m tcp -p ...

  8. Jmeter调用JAVA jar包传参

    http://blog.csdn.net/xiazdong/article/details/7873767#

  9. throw UnsupportedOperationException

    package org.usc.action; import java.util.ArrayList; import java.util.Arrays; import java.util.List; ...

  10. SQL 语句(原生)

    //查 //查询表里的所有数据 select * from 表名 //根据id等字段查询数据 select * from 表名 where 字段 = 值 or 字段 = 值 (例):select * ...