在ASP.NET中实现CDN的最佳方式

时间:2015-08-14 09:56:02

标签: c# asp.net httpmodule

我需要在ASP.NET项目中实现CDN。我能提出的最好的想法是创建一个自定义的HttpModule,它将处理 PostRequestHandlerExecute 事件。在将响应发送到客户端之前,我将所有静态URL域替换为CDN的区域URL。

这是我的模块代码:

using System;
using System.Configuration;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

public class CdnModule : IHttpModule
{
    public static string CdnUrl;
    public CdnModule()
    {
        CdnUrl = ConfigurationManager.AppSettings["CdnUrl"];
    }

    public String ModuleName
    {
        get { return "CdnModule"; }
    }

    // register handlers 
    public void Init(HttpApplication app)
    {
        app.PostRequestHandlerExecute += PostRequestHandlerExecuteHandler;
    }
    private void PostRequestHandlerExecuteHandler(object sender, EventArgs e)
    {
        var response = HttpContext.Current.Response;
        if (response.ContentType == "text/html")
        {
            response.Filter = new UrlFilter(response.Filter);
        }
    }

    public void Dispose() { }
}

public class UrlFilter : Stream
{
    private Stream _responseStream;
    StringBuilder _responseHtml;

    public UrlFilter(Stream inputStream)
    {
        _responseStream = inputStream;
        _responseHtml = new StringBuilder();
    }

    #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; set; }

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

    public override void SetLength(long length)
    {
        _responseStream.SetLength(length);
    }

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

    #endregion


    //Here I'm replacing URLs

    public override void Write(byte[] buffer, int offset, int count)
    {
        var html = Encoding.UTF8.GetString(buffer, offset, count);

        //replace relative UploadFile urls with absolute CDN zone
        html = html.Replace("\"/UploadFile/", "\"" + CdnModule.CdnUrl + "/UploadFile/");

        buffer = Encoding.UTF8.GetBytes(html);

        _responseStream.Write(buffer, 0, buffer.Length);
    }
    #endregion
}

下面的代码负责拦截和修改响应文本:

    public override void Write(byte[] buffer, int offset, int count)
    {
        var html = Encoding.UTF8.GetString(buffer, offset, count);

        //replace relative UploadFile urls with absolute CDN zone
        html = html.Replace("\"/UploadFile/", "\"" + CdnModule.CdnUrl + "/UploadFile/");

        buffer = Encoding.UTF8.GetBytes(html);

        _responseStream.Write(buffer, 0, buffer.Length);
    }

我做得对吗?或者有更好的方法吗?

谢谢!

0 个答案:

没有答案