zoukankan      html  css  js  c++  java
  • [转]Asp.net2.0 中自定义过滤器对Response内容进行处理

    在Module中使用自定义过滤器,来统一对站内所有请求响应的输出内容进行采集或更改。 因项目需要,对每一个访问网站的请求要做原始数据记录,其中要包括几个要素:
    1.客户端的IP
    2.客户端请求的页面路径
    3.客户端发出的请求头
    4.服务器返回的正文内容。

    在代码设计前分析了一下,前三个都很好解决,对于截获服务器返回的正文,准备用HttpResponse 对象中的Output 和 OutputStream 属性输出信息来解决。

    可是在正式编码的过程中,发现Output和OutputStream 并不是想像中可以直接把数据转出取回,耗费了近两天的时间,想尽了一切办法可还是仅仅可以追加内容并无法读取。

    在网上查阅到,对于HttpResponse 对象,仅仅可以使用过滤器来对其中将要输出的内容进行修改。
    这个过滤器要继承自Stream 类,并要实现其中的虚方法。看来之前企图使用HttpWriter,TextWriter,Stream,HttpStream 这些类来转出数据完全是错误的。

    现在有信心来截获服务器返回内容了,说干就干吧!

    1.首先要建立一个简易过滤器。
    代码如下:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.IO;
    using System.Web;

        /**//// <summary>
        /// 定义原始数据EventArgs,便于在截获完整数据后,由事件传递数据
        /// </summary>
        public class RawDataEventArgs : EventArgs
        {
            private string sourceCode;

            public RawDataEventArgs(string SourceCode)
            {
                sourceCode = SourceCode;
            }
            public string SourceCode
            {
                get { return sourceCode; }
                set { sourceCode = value; }
            }
        }

    //自定义过滤器
        public class RawFilter : Stream
        {

            Stream responseStream;
            long position;
            StringBuilder responseHtml;

            /**//// <summary>
            /// 当原始数据采集成功后激发。
            /// </summary>
            public event EventHandler<RawDataEventArgs> OnRawDataRecordedEvent;

            public RawFilter(Stream inputStream)
            {
                responseStream = inputStream;
                responseHtml = new StringBuilder();
            }

    //实现Stream 虚方法
            Filter Overrides#region Filter Overrides

            public override bool CanRead
            {
                get
                {
                    return true;
                }
            }

            public override bool CanSeek
            {
                get
                {
                    return true;
                }
            }

            public override bool CanWrite
            {
                get
                {
                    return true;
                }
            }
            public override void Close()
            {
                responseStream.Close();
            }

            public override void Flush()
            {
                responseStream.Flush();
            }

            public override long Length
            {
                get
                {
                    return 0;
                }
            }

            public override long Position
            {
                get
                {
                    return position;
                }
                set
                {
                    position = value;
                }
            }

            public override int Read(byte[] buffer, int offset, int count)
            {
                return responseStream.Read(buffer, offset, count);
            }

            public override long Seek(long offset, SeekOrigin origin)
            {
                return responseStream.Seek(offset, origin);
            }

            public override void SetLength(long length)
            {
                responseStream.SetLength(length);
            }
            #endregion

    //关键的点,在HttpResponse 输入内容的时候,一定会调用此方法输入数据,所以要在此方法内截获数据
            public override void Write(byte[] buffer, int offset, int count)
            {
                string strBuffer = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);

    //采用正则,检查输入的是否有页面结束符</html>
                Regex eof = new Regex(“</html>”, RegexOptions.IgnoreCase);

                if (!eof.IsMatch(strBuffer))
                {
                  //页面没有输出完毕,继续追加内容
                    responseHtml.Append(strBuffer);
                }
                else
                {
                  //页面输出已经完毕,截获内容
                    responseHtml.Append(strBuffer);
                    string finalHtml = responseHtml.ToString();

                //激发数据已经获取事件
                OnRawDataRecordedEvent(this, new RawDataEventArgs(finalHtml));

                    //继续传递要发出的内容写入流
                    byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(finalHtml);

                    responseStream.Write(data, 0, data.Length);
                }
            }
        }
    至此,过滤器定义完毕了,接下来还需要把这个过滤器装配到HttpResponse 对象中。
    为了能够截获整站的aspx 页面输出的内容,我们可以定义一个HttpModule 来完成。
    代码如下:
    using System;
    using System.Web;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Diagnostics;

        public class HttpRawDataModule : IHttpModule
        {
            IHttpModule 成员#region IHttpModule 成员

            public void Dispose()
            {

    }

            public void Init(HttpApplication context)
            {
                //绑定事件,在对此请求处理过程全部结束后进行过滤操作
                context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
            }

            #endregion

            /**//// <summary>
            /// 对此HTTP请求处理的过程全部结束
            /// </summary>
            /// <param name=”sender”></param>
            /// <param name=”e”></param>
            void context_ReleaseRequestState(object sender, EventArgs e)
            {
                HttpApplication application = (HttpApplication)sender;

                //这里需要针对ASPX页面进行拦截,测试发现如果不这么做,Wap 访问站点图片容易显示为X,奇怪
                string[] temp = application.Request.CurrentExecutionFilePath.Split(‘.’);
                if (temp.Length > 0 && temp[temp.Length - 1].ToLower() == “aspx”)
                {
                    //装配过滤器
                    application.Response.Filter = new RawFilter(application.Response.Filter);

                    //绑定过滤器事件
                    RawFilter filter = (RawFilter)application.Response.Filter;
                    filter.OnRawDataRecordedEvent += new EventHandler<RawDataEventArgs>(filter_OnRawDataRecordedEvent);
                }
            }

            /**//// <summary>
            /// 当原始数据采集到以后,入库
            /// </summary>
            /// <param name=”sender”></param>
            /// <param name=”e”></param>
            void filter_OnRawDataRecordedEvent(object sender, RawDataEventArgs e)
            {
                string allcode = e.SourceCode;
                WapSite.SiteDataClass wapdata = new WapSite.SiteDataClass();
                wapdata.WriteRawDataLog(allcode);
            }
        }

    HttpModule 准备完毕,也装配上了过滤器,接下来还需要在配置文件中配置HttpModules配置节 ,把自定义的HttpModule 加入到HTTP处理管道中。
    在Web.config 中增加配置节如下:
      <system.web>
        <httpModules>
          <add name=”RawDataModule” type=”HttpRawDataModule”/>
        </httpModules>
      </system.web>
    测试成功,能准确的获得服务器向客户端输出的HTML内容。

    其中,在过滤器中,可以直接对即将要输出的内容做 对于字符串的任意处理。

    而且采用这样的方式来对站点即将输出的内容做修改和采集,可以通过修改配置文件,随时打开和关闭,有很强的优越性和灵活性还有重用性。

    记得看到过很多需要产生静态页面的网站,都是通过代码HttpWebRequest 向自己请求并记录返回的代码产生静态页面,不知道我当前介绍的方法是否更好写,比如需要产生静态页面时,不管是谁发出请求,由服务器检查自己是否有静态页面,否则产生静态页面,并转向。给出引子,希望大家还是自己开阔思路比较好。

    来源:北风网

  • 相关阅读:
    Kafka 生产者 自定义分区策略
    同步互斥
    poj 1562 Oil Deposits(dfs)
    poj 2386 Lake Counting(dfs)
    poj 1915 KnightMoves(bfs)
    poj 1664 放苹果(dfs)
    poj 1543 Perfect Cubes (暴搜)
    poj 1166 The Clocks (暴搜)
    poj 3126 Prime Path(bfs)
    处理机调度
  • 原文地址:https://www.cnblogs.com/20m13v08c15/p/3502244.html
Copyright © 2011-2022 走看看