是否可以从托管的HttpModule调用IIS 7+ setUrl API?

时间:2010-11-02 11:11:24

标签: asp.net iis-7 httpmodule

我基本上需要的是管理大量的URL重写和重定向。重定向很容易,但重写应该通过IIS中的ARR代理进行代理。据我所知,IIS重写模块使用IIS中的本机setUrl API来获取ARR代理来转发请求。我不能完成编写本机模块的任务,所以我认为可以编写一个托管模块来做同样的事情。

@CarlosAg:只是为了扩展我对你答案的评论。下面是我需要设置的规则和提供程序,以使重写模块完成我想要的操作。它只是我或者它似乎有点像操纵重写模块做一些它不应该做的事情吗?

<rewrite>
  <providers>
    <provider name="CustomRewrite" type="MyRewriteProviders.RewriteProvider, MyRewriteProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e72501f8a0edfe78" />
    <provider name="CustomRedirectTemporary" type="MyRewriteProviders.RedirectTemporaryProvider, MyRewriteProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e72501f8a0edfe78" />
    <provider name="CustomRedirectPermanent" type="MyRewriteProviders.RedirectPermanentProvider, MyRewriteProviders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e72501f8a0edfe78" />
  </providers>
  <rules>
    <clear />
    <rule name="Set Http">
      <match url="." />
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
      <serverVariables>
        <set name="RequestProtocol" value="http" />
      </serverVariables>
      <action type="None" />
    </rule>
    <rule name="Set Https">
      <match url="." />
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{HTTPS}" pattern="ON" />
      </conditions>
      <serverVariables>
        <set name="RequestProtocol" value="https" />
      </serverVariables>
      <action type="None" />
    </rule>
    <rule name="Custom Rewrite">
      <match url="(.*)" />
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{CustomRewrite:{RequestProtocol}://{HTTP_HOST}/{URL}}" pattern="(.+)" />
      </conditions>
      <action type="Rewrite" url="{C:1}" logRewrittenUrl="true" />
    </rule>
    <rule name="Custom Redirect (Temporary)" stopProcessing="true">
      <match url="(.*)" />
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{CustomRedirectTemporary:{RequestProtocol}://{HTTP_HOST}/{URL}}" pattern="(.+)" />
      </conditions>
      <action type="Redirect" url="{C:1}" redirectType="Found" appendQueryString="false" />
    </rule>
    <rule name="Custom Redirect (Permanent)" stopProcessing="true">
      <match url="(.*)" />
      <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
        <add input="{CustomRedirectPermanent:{RequestProtocol}://{HTTP_HOST}/{URL}}" pattern="(.+)" />
      </conditions>
      <action type="Redirect" url="{C:1}" appendQueryString="false" />
    </rule>
  </rules>
</rewrite>

提供者的代码:

using System;
using System.Collections.Generic;
using Microsoft.Web.Iis.Rewrite;

namespace MyRewriteProviders
{
    public enum ActionType
    {
        Rewrite,
        RedirectPermanent,
        RedirectTemporary
    }

    public abstract class BaseProvider : IRewriteProvider
    {
        protected abstract ActionType Action { get; }

        public void Initialize(IDictionary<string, string> settings, IRewriteContext rewriteContext) {}

        public string Rewrite(string value)
        {
            return RewriteEngine.RewriteUri(value, ActionType.Rewrite);
        }
    }

    public class RewriteProvider : BaseProvider
    {
        protected override ActionType Action
        {
            get { return ActionType.Rewrite; }
        }
    }

    public class RedirectTemporaryProvider : BaseProvider
    {
        protected override ActionType Action
        {
            get { return ActionType.RedirectTemporary; }
        }
    }

    public class RedirectPermanentProvider : BaseProvider
    {
        protected override ActionType Action
        {
            get { return ActionType.RedirectPermanent; }
        }
    }

    public static class RewriteEngine
    {
        public static string RewriteUri(string uri, ActionType action)
        {
            // Not actual rule engine implementation... just to demonstrate what it would do.
            var ub = new UriBuilder(uri);

            // Simulate a match on a rewrite rule
            if (string.Equals(ub.Host, "rewrite.com", StringComparison.InvariantCultureIgnoreCase) && action == ActionType.Rewrite)
            {
                ub.Host = "rewrite-rewritten.com";
                return ub.ToString();
            }

            // Simulate a match on a temporary redirect rule
            if (string.Equals(ub.Host, "redirect.com", StringComparison.InvariantCultureIgnoreCase) && action == ActionType.RedirectTemporary)
            {
                ub.Host = "redirect-rewritten.com";
                return ub.ToString();
            }

            // No rules matched. This will make the condition in the rewrite rule not match.
            return string.Empty;
        }
    }
}

除此之外,您需要设置IIS以允许自定义服务器变量,并且您需要在gac中签名并注册提供程序...这似乎只是为了能够操作请求URL而复杂一点就像你来自本土的api。

2 个答案:

答案 0 :(得分:0)

您是否考虑过使用URL Rewrite extensibility?你可以轻松地创建一个可以映射任何东西的提供者,你可以通过参数传递任何信息(只有一个字符串,但你可以用一些分隔符连接任意数量的字符串),然后解决你需要的任何信息,无论是否是部分URL的字符串,或整个网址。

请参阅:http://learn.iis.net/page.aspx/804/developing-a-custom-rewrite-provider-for-url-rewrite-module/

答案 1 :(得分:0)

我最终使用了ManagedFusion rewriter。主要原因是该模块看起来相当可扩展,并且还具有内置代理。无论是否表现,只有时间和几个测试都能说明。