一个简易的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
    }
时间: 2024-08-30 08:34:35

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

手写一个简易的ajax请求

function ajax(url){ const p=new Promise((resolve,reject)=>{ const xhr=XMLHttpRequest() xhr.open('GET','/data/test.json',true) xhr.onreadystatechange=function(){ if(xhr.readyState===4){ if(xhr.status===200){ JSON.parse(xhr.responseText) }else if(xhr.s

Socket 初识 用Socket建立一个简易Web服务器

摘自<Asp.Net 本质论>作者:郝冠军 //在.Net中.system.Net命名空间提供了网络编程的大多数数据据类型以及常用操作,其中常用的类型如下:/*IPAddress 类表示一个IP地址* IPEndPoint类用来表示一个IP地址和一个端口号的组合,成为网络的端点.* System.Net.Sockets命名空间中提供了基于Socked编程的数据类型.* Socket类封装了Socked的操作.* 常见的操作:* Listen:设置基于连接通信的Socket进入监听状态,并设置等

Tinywebserver:一个简易的web服务器

这是学习网络编程后写的一个练手的小程序,可以帮助复习I/O模型,epoll使用,线程池,HTTP协议等内容. 程序代码是基于<Linux高性能服务器编程>一书编写的. 首先回顾程序中的核心内容和主要问题,最后给出相关代码. 0. 功能和I/O模型 实现简易的HTTP服务端,现仅支持GET方法,通过浏览器访问可以返回相应内容. I/O模型采用Reactor(I/O复用 + 非阻塞I/O) + 线程池. 使用epoll事件循环用作事件通知,如果listenfd上可读,则调用accept,把新建的f

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

即便再简陋的服务器也是服务器,今天就来循着书本的第二章来看看如何实现一个servlet容器. 背景知识 既然说到servlet容器这个名词,我们首先要了解它到底是什么. servlet 相比你或多或少有所了解.servlet是用java编写的服务器端程序,主要功能在于交互式地浏览和修改数据,生成动态Web内容.狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者. 容器 容器的概念很大,在这里

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

引言 做一个老实人挺好的,至少还觉得自己挺老实的. 再分享一首 自己喜欢的诗人的一首 情景诗. 每个人总会有问题,至少喜欢就好, 本文 参照 http 协议   http://www.cnblogs.com/rayray/p/3729533.html html格式   http://blog.csdn.net/allenjy123/article/details/7375029 tinyhttpd 源码    https://github.com/EZLippi/Tinyhttpd 附录 本文最

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

一.引言 上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中.本篇博文将使用AngularJS来打造一个简易的权限管理系统.下面不多说,直接进入主题. 二.整体架构设计介绍 首先看下整个项目的架构设计图: 从上图可以看出整个项目的一个整体结构,接下来,我来详细介绍了项目的整体架构: 采用Asp.net Web API来实现REST 服务.这样的实现方式,已达到后端服务的公用.分别部署和更好地扩展.Web层依赖应用服务接口,并且使

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

前言 经过不断的坚持和努力,ENode 2.0的第一个真实案例终于出来了.这个案例是一个简易的论坛,开发这个论坛的初衷是为了验证用ENode框架来开发一个真实项目的可行性.关于ENode是什么,本文就不多介绍了,可以参考这篇文章的介绍.本文重点介绍一下ENode是如何帮助我们开发一个基于DDD+CQRS+Event Sourcing架构的应用程序的.这个论坛使用到了ENode, EQueue两个框架,EQueue是一个分布式的消息队列组件,该组件的主体思想是参考阿里的RocketMQ.当我们使用

一个简易的web服务器:Tinywebserver

这是学习网络编程后写的一个练手的小程序,可以帮助复习I/O模型,epoll使用,线程池,HTTP协议等内容. 程序代码是基于<Linux高性能服务器编程>一书编写的. 首先回顾程序中的核心内容和主要问题,最后给出相关代码. 0. 功能和I/O模型 实现简易的HTTP服务端,现仅支持GET方法,通过浏览器访问可以返回相应内容. I/O模型采用Reactor(I/O复用 + 非阻塞I/O) + 线程池. 使用epoll事件循环用作事件通知,如果listenfd上可读,则调用accept,把新建的f

AngularJs打造一个简易权限系统

AngularJs打造一个简易权限系统 一.引言 上一篇博文已经向大家介绍了AngularJS核心的一些知识点,在这篇博文将介绍如何把AngularJs应用到实际项目中.本篇博文将使用AngularJS来打造一个简易的权限管理系统.下面不多说,直接进入主题. 二.整体架构设计介绍 首先看下整个项目的架构设计图: 从上图可以看出整个项目的一个整体结构,接下来,我来详细介绍了项目的整体架构: 采用Asp.net Web API来实现REST 服务.这样的实现方式,已达到后端服务的公用.分别部署和更好