创建 HTTP 模块与创建可以实现 ihttpmodule 接口的类一样简单。ihttpmodule 接口定义了两种方法:
? | Init(HttpApplication)。此方法在初始化 HTTP 模块后触发。在此方法中,您将把事件处理程序绑定到相应的 httpapplication 事件。 |
? | Dispose()。当请求已完成并已发送回 IIS 时调用此方法。您应当在此处执行所有最终的清除操作。 |
为了便于为 URL 重写创建 HTTP 模块,我将从创建抽象基类 basemodulerewriter 开始介绍。此类将实现 ihttpmodule。在 Init() 事件中,它将 httpapplication 的 authorizerequest 事件绑定到 basemodulerewriter_authorizerequest 方法。basemodulerewriter_authorizerequest 方法将调用该类传入被请求的 path 的 rewrite() 方法,以及传入 init() 方法的 httpapplication 对象。rewrite() 方法是抽象的,也就是说,在 basemodulerewriter 类中,rewrite() 方法没有方法主体;从 basemodulerewriter 派生而来的类必须覆盖此方法并提供方法主体。
具有此基类后,只需创建由 basemodulerewriter 派生的类即可,该类可以覆盖 rewrite() 并在那里执行 URL 重写逻辑。下面显示了 basemodulerewriter 的代码。
public abstract class BaseModuleRewriter : IHttpModule{ public virtual void Init(HttpApplication app) { // 警告!此代码不适用于 Windows 身份验证! // 如果使用 Windows 身份验证, // 请改为 app.BeginRequest app.AuthorizeRequest += new EventHandler(this.BaseModuleRewriter_AuthorizeRequest); } public virtual void Dispose() {} protected virtual void BaseModuleRewriter_AuthorizeRequest( object sender, EventArgs e) { HttpApplication app = (HttpApplication) sender; Rewrite(app.Request.Path, app); } protected abstract void Rewrite(string requestedPath, HttpApplication app);}
请注意,BaseModuleRewriter 类将在 authorizerequest 事件中执行 URL 重写。如上所述,如果将 Windows 身份验证与文件授权结合使用,您需要对此做出更改,以便可以在 beginrequest 或 authenticaterequest 事件中执行 URL 重写。
ModuleRewriter 类扩展了 basemodulerewriter 类,并负责执行实际的 URL 重写。modulerewriter 包含单一覆盖方法(rewrite()),如下所示:
protected override void Rewrite(string requestedPath, System.Web.HttpApplication app){ // 获得配置规则 RewriterRuleCollection rules = RewriterConfiguration.GetConfig().Rules; // 遍历每个规则 for(int i = 0; i < rules.Count; i++) { // 获得要查找的模式,并且 // 解析 Url(转换为相应的目录) string lookFor = "^" + RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].LookFor) + "$"; // 创建 regex(请注意,已设置 IgnoreCase) Regex re = new Regex(lookFor, RegexOptions.IgnoreCase); // 查看是否找到了匹配的规则 if (re.IsMatch(requestedPath)) { // 找到了匹配的规则 -- 进行必要的替换 string sendToUrl = RewriterUtils.