这两天一直再看微信开发,临时在我的电脑搭了个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. nginx开发_Filter模块执行顺序

    Filter模块执行顺序 Filter模块的执行顺序是在执行configure文件时决定的,configure文件执行完成后生成objs/ngx_modules.c,文件中定义了一个数组ngx_mod ...

  2. webpack 基本功能和原理

    依赖管理:方便引用第三方模块.让模块更容易复用.避免全局注入导致的冲突.避免重复加载或加载不需要的模块. 合并代码:把各个分散的模块集中打包成大文件,减少HTTP的请求链接数,配合UglifyJS可以 ...

  3. Java应用架构设计模块化模式与OSGI摘录

    在Java中,最适合模块化的单元就是Jar文件. 代码层面我们关注的太多了,熟练的开发人员现在很少争论使用模式的好处,也不再识别哪个模式适合当前需要,因为都能够本能地使用各种设计原则和模式,从GoF的 ...

  4. PYTHON 异常处理 二 TRY 模块

    异常处理 捕捉异常可以使用try/except语句. try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理. 如果你不想在异常发生时结束你的程序,只需在try ...

  5. java命令行从编译到打jar包到执行

     目录: 一. javac编译     1. 没有额外的jar包     2. 包含额外的jar包 二. jar打jar包 三. java运行     1. java命令执行     2. jar包执 ...

  6. monkey基本命令及脚本编写

    Monkey 是Android自带的黑盒测试工具,一般通过随机触发界面事件,来确定应用是否会发生异常,多用于android应用的稳定性.压力测试  基本命令: adb shell monkey [op ...

  7. 清理win10系统c盘

    本人C盘是128G SSD硬盘,Win10系统盘和一些常用的程序都装在这个盘(特大程序除外),目的是为了使用这些程序时提高响应速度.但是本人电脑使用1年,突然发现C盘以占用近70G的空间,实在是吓蒙撒 ...

  8. TypeScript完全解读(26课时)_13.TypeScript完全解读-高级类型(2)

    13.TypeScript完全解读-高级类型(2) 高级类型中文网的地址:https://typescript.bootcss.com/advanced-types.html 创建文件并在index. ...

  9. struts2 中的 addActionError 、addFieldError、addActionMessage的方法

    addActionError .addFieldError.addActionMessage都是ActionSupport的方法 一.addActionError("错误内容"): ...

  10. CodeForces 496D Tennis Game (暴力枚举)

    题意:进行若干场比赛,每次比赛两人对决,赢的人得到1分,输的人不得分,先得到t分的人获胜,开始下场比赛,某个人率先赢下s场比赛时, 游戏结束.现在给出n次对决的记录,问可能的s和t有多少种,并按s递增 ...