我需要在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);
}
我做得对吗?或者有更好的方法吗?
谢谢!