一个简易的Http请求转发器
这两天一直再看微信开发,临时在我的电脑搭了个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请求转发器的更多相关文章
- .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”
FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...
- 探秘Tomcat——一个简易的Servlet容器
即便再简陋的服务器也是服务器,今天就来循着书本的第二章来看看如何实现一个servlet容器. 背景知识 既然说到servlet容器这个名词,我们首先要了解它到底是什么. servlet 相比你或多或少 ...
- [后端人员耍前端系列]AngularJs篇:使用AngularJs打造一个简易权限系统
一.引言 上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中.本篇博文将使用AngularJS来打造一个简易的权限管理系统.下面不多 ...
- ENode 2.0 - 第一个真实案例剖析-一个简易论坛(Forum)
前言 经过不断的坚持和努力,ENode 2.0的第一个真实案例终于出来了.这个案例是一个简易的论坛,开发这个论坛的初衷是为了验证用ENode框架来开发一个真实项目的可行性.目前这个论坛在UI上是使用了 ...
- C 实现一个简易的Http服务器
引言 做一个老实人挺好的,至少还觉得自己挺老实的. 再分享一首 自己喜欢的诗人的一首 情景诗. 每个人总会有问题,至少喜欢就好, 本文 参照 http 协议 http://www.cnblogs. ...
- AngularJs打造一个简易权限系统
AngularJs打造一个简易权限系统 一.引言 上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中.本篇博文将使用AngularJ ...
- Tinywebserver:一个简易的web服务器
这是学习网络编程后写的一个练手的小程序,可以帮助复习I/O模型,epoll使用,线程池,HTTP协议等内容. 程序代码是基于<Linux高性能服务器编程>一书编写的. 首先回顾程序中的核心 ...
- 使用 RxJS 实现一个简易的仿 Elm 架构应用
使用 RxJS 实现一个简易的仿 Elm 架构应用 标签(空格分隔): 前端 什么是 Elm 架构 Elm 架构是一种使用 Elm 语言编写 Web 前端应用的简单架构,在代码模块化.代码重用以及测试 ...
- day-1 用python编写一个简易的FTP服务器
从某宝上购买了一份<Python神经网络深度学习>课程,按照视频教程,用python语言,写了一个简易的FTP服务端和客户端程序,以前也用C++写过聊天程序,编程思路差不多,但是pytho ...
随机推荐
- hdu-5666 Segment(俄罗斯乘法or大数乘法取模)
题目链接: Segment Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) P ...
- linux安装flume及问题
验证是否安装成功: [root@master conf]# /usr/local/src/apache-flume-1.6.0-bin/bin/flume-ng versionError: Could ...
- C++之虚函数与虚继承详解
准备工作 1.VS2012使用命令行选项查看对象的内存布局 微软的Visual Studio提供给用户显示C++对象在内存中的布局的选项:/d1reportSingleClassLayout.使用方法 ...
- AtCoder Grand Contest 014 E:Blue and Red Tree
题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_e 题目翻译 有一棵有\(N\)个点的树,初始时每条边都是蓝色的,每次你可以选择一条由蓝色边构 ...
- bzoj 3745 [Coci2015]Norma——序列分治
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3745 如果分治,就能在本层仅算过 mid 的区间了. 可以从中间到左边地遍历左边,给右边两个 ...
- asio 中strand的作用
namespace { // strand提供串行执行, 能够保证线程安全, 同时被post或dispatch的方法, 不会被并发的执行. // io_service不能保证线程安全 boost::a ...
- css样式 -- 表格不会因为字体过长导致字体溢出的问题
常常碰到因为表格大小就麽大了,字体过长会爆炸溢出的问题,我们后端就用这个可以了,溢出的可以省略号 ... 代替好了. /* 在表格css样式加上这三个就可以了 效果就会变成 “abc...” */ { ...
- Cube 数据 与 DW 数据对应不上
场景: 时间维度表:字段(日期) 收费事实表:字段(金额,收费日期,就诊编号) 管理:使用维度表的 日期字段与事实表的 收费日期字段 进行关联,建立多维度数据集. 问题: DW : 9月份 ...
- eclipse编辑窗口不见了(打开左边的java、xml文件,中间不会显示代码)
转自:https://blog.csdn.net/u012062810/article/details/46729779?utm_source=blogxgwz4 1. windows-->re ...
- [hdu1277]全文检索(AC自动机)
解题关键:AC自动机模板题,注意字符匹配时若无法匹配,直接用%s即可. #include<bits/stdc++.h> using namespace std; typedef long ...