在 URL 重写模块中使用重写映射

作者:Ruslan Yakushev

本演练介绍 URL 重写模块中重写映射的概念,并指导你创建使用重写映射的重写规则。 在本演练中,你将创建两个重写映射:一个重写映射由执行 url 重写的规则使用,另一个重写映射由执行重定向到不同域的规则使用。

背景

重写映射是名称和值对的任意集合,可在重写规则中用于在重写期间生成替换 URL。 当你有一大套重写规则时,重写映射特别有用,所有这些规则都使用静态字符串(例如没有使用模式匹配时)。 在这种情况下,可以将输入 URL 和替换 URL 之间的所有映射(作为键和值)放入重写映射中,而不要定义大量简单的重写规则。 然后,在根据输入 URL 查找替换 URL 时,将有一个引用此重写映射的重写规则。

先决条件

本演练要求满足以下先决条件:

  1. 启用了 ASP.NET 角色服务的 IIS 7.0 或更高版本
  2. 已安装 URL 重写 Go Live 版本

设置测试网页

为了演示重写映射功能,我们将使用一个简单的测试 asp.net 页。 此页读取 Web 服务器变量并在浏览器中输出其值。

复制以下 ASP.NET 代码,并将其放入名为“article.aspx”的文件中的 %SystemDrive%\inetpub\wwwroot\ 文件夹中:

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>URL Rewrite Module Test</title>
</head>
<body>
      <h1>URL Rewrite Module Test Page</h1>
      <table>
            <tr>
                  <th>Server Variable</th>
                  <th>Value</th>
            </tr>
            <tr>
                  <td>Original URL: </td>
                  <td><%= Request.ServerVariables["HTTP_X_ORIGINAL_URL"] %></td>
            </tr>
            <tr>
                  <td>Final URL: </td>
                  <td><%= Request.ServerVariables["SCRIPT_NAME"] + "?" + Request.ServerVariables["QUERY_STRING"] %></td>
            </tr>
      </table>
</body>
</html>

复制此文件后,浏览到 http://localhost/article.aspx 并检查系统是否已在浏览器中正确呈现页面。

Screenshot that shows the test page rendered in a browser.

创建重写映射

首先,我们创建一个重写映射和重写规则,用于根据原始 URL 和重写 URL 之间的一组静态映射来执行 URL 重写。 若要创建重写映射,请执行以下步骤:

  1. 转到 IIS 管理器

  2. 选择“默认网站”

  3. 在功能视图中,单击“URL 重写”
    Screenshot that shows U R L Rewrite in Features View.

  4. 在右侧的“操作”窗格中,单击“查看重写映射...”:
    Screenshot that shows View rewrite maps...

  5. 在右侧站点的“操作”窗格中,单击“添加重写映射...”,然后输入“StaticRewrites”作为重写映射名称
    Screenshot that shows the Rewrite map name box.

  6. 在新建的重写映射页上的右侧“操作”窗格中,单击“添加映射条目...”,然后分别在“原始值:”和“新值:”文本框中,输入“/article”和“/article.aspx?id=1&title=some-title”。 原始值指定我们要重写的源 URL 路径;新值指定我们要重写为的 URL 路径。
    Screenshot that shows the Original value and New value boxes.

  7. 重复步骤 6 将以下映射添加到重写映射中:

    原始值: 新值:
    /some-title /article.aspx?id=1&title=some-title
    /post/some-title.html /article.aspx?id=1&title=some-title

现在打开网站的 web.config 文件(如果使用默认网站,可以在 %SystemDrive%\inetpub\wwwroot 找到 web.config)。 应会看到以下部分:

<rewrite>
    <rewriteMaps>
        <rewriteMap name="StaticRewrites" defaultValue="">
            <add key="/article1" value="/article.aspx?id=1&amp;title=some-title" />
            <add key="/some-title" value="/article.aspx?id=1&amp;title=some-title" />
            <add key="/post/some-title.html" value="/article.aspx?id=1&amp;title=some-title" />
        </rewriteMap>
    </rewriteMaps>
</rewrite>

此重写映射名为“StaticRewrites”,用于将传入 URL(定义为重写映射中的键)重写为其内部表示形式(定义为值)defaultValue 属性指定在映射中尚未定义传入 URL 时要使用的值。 在本例中,将返回一个空字符串。

请注意,键及其与值的关系没有明显的共同模式。 这意味着无法使用正则表达式或通配符来定义 URL 转换逻辑。 此外,这意味着如果没有使用重写映射,我们将不得不创建三个重写规则。 使用重写映射只能创建一个重写规则。 下一部分将介绍如何创建使用此重写映射的重写规则。

从重写规则引用重写映射

若要创建使用重写映射的重写规则,请将以下 XML 代码复制并粘贴到网站的 web.config 文件的 <rewrite> 部分:

<rules>
    <rule name="Rewrite Rule">
        <match url=".*" />
        <conditions>
            <add input="{StaticRewrites:{REQUEST_URI}}" pattern="(.+)" />
        </conditions>
        <action type="Rewrite" url="{C:1}" />
    </rule>
</rules>

让我们仔细查看每个规则元素以了解其作用:
<match url=".*" /> - 此元素告知 URL 重写模块匹配任何传入 URL(通过使用正则表达式特殊字符“.”)

<add input="{StaticRewrites:{REQUEST\_URI}}" pattern="(.+)"> - 此条件检查从重写映射 StaticRewrites 返回的值是否不是空字符串。 为了执行此项检查,服务器变量 REQUEST_URI 的值将作为参数传递给重写映射。 如果重写映射包含带有键的条目(即与 REQUEST_URI 相同),则将返回与该键对应的值。 正则表达式模式将仅匹配非空字符串,因此如果从映射返回空字符串,则条件将计算为 false,因此不会执行重写。 如果返回非空字符串,则由于模式中使用了括号,该字符串将在反向引用中被捕获。

<action type="Rewrite" url="{C:1}" /> - 此元素指定 URL 重写模块需要使用从重写映射中提取的新 URL 字符串来重写当前 URL 字符串。 请注意,url 属性引用了条件反向引用 {C:1},该条件反向引用是在条件中的模式匹配时设置的。

测试重写规则

若要测试使用“StaticRewrites”映射的重写规则,请打开 Web 浏览器并请求以下任意 URL:

http://localhost/article1
http://localhost/some-title
http://localhost/post/some-title.html

上述任何一个 URL 都应该导致 URL 根据重写映射中定义的映射进行重写。 结果应如下所示:

Screenshot that shows the results of the test.

使用重写映射进行重定向

现在我们将创建另一个重写映射,用于定义源 URL 和重定向 URL 之间的静态映射。 若要创建重写映射,请按照创建重写映射部分中所述的相同步骤进行操作,但需将重写映射命名为“StaticRedirects”并使用以下映射条目值:

原始值: 新值:
/old-article.aspx?id=1 /article.aspx?id=1
/posts/default.aspx?id=1 /article.aspx?id=1
/old-title.html /article.aspx?id=1

网站的 web.config 文件现在应包含以下两个重写映射:

<rewriteMaps>
    <rewriteMap name="StaticRewrites">
        <add key="/article1" value="/article.aspx?id=1&amp;title=some-title" />
        <add key="/some-title" value="/article.aspx?id=1&amp;title=some-title" />
        <add key="/post/some-title.html" value="/article.aspx?id=1&amp;title=some-title" />
    </rewriteMap>
    <rewriteMap name="StaticRedirects">
        <add key="/old-article.aspx?id=1" value="/article.aspx?id=1" />
        <add key="/posts/default.aspx?id=1" value="/article.aspx?id=1" />
        <add key="/old-title.html" value="/article.aspx?id=1" />
    </rewriteMap>
</rewriteMaps>

若要创建使用 StaticRedirects 重写映射的规则,请将以下规则定义复制并粘贴到网站的 web.config 文件中:

<rules>
    <rule name="Redirect Rule" stopProcessing="true">
        <match url=".*" />
        <conditions>
            <add input="{StaticRedirects:{REQUEST_URI}}" pattern="(.+)" />
        </conditions>
        <action type="Redirect" url="http://localhost{C:1}" appendQueryString="False" redirectType="Permanent" />
    </rule>
</rules>

同样,让我们仔细查看每个规则元素以了解其作用:
<match url=".*" /> - 此元素告知 URL 重写模块匹配任何传入 URL(通过使用正则表达式特殊字符“.”)

<add input="{StaticRedirects:{REQUEST\_URI}}" pattern="(.+)"> - 此条件检查从重写映射 StaticRedirects 返回的值是否不是空字符串。 为了执行此项检查,服务器变量 REQUEST_URI 的值将作为参数传递给重写映射。 如果重写映射包含带有键的条目(即与 REQUEST_URI 相同),则将返回与该键对应的值。 正则表达式模式将仅匹配非空字符串,因此如果从映射返回空字符串,则条件将计算为 false,因此不会执行重写。 如果返回非空字符串,则由于模式中使用了括号,该字符串将在反向引用中被捕获。

<action type="Redirect" url="http://localhost{C:1}" appendQueryString="False" redirectType="Permanent" /> - 此元素指定 URL 重写模块需要将 Web 客户端重定向到一个新 URL,该 URL 是通过连接新域名(在本例中为简单起见,它是同一个域)和 StaticRedirects 映射返回的重定向 URL 路径而构造的。

测试重定向规则

若要测试使用“StaticRedirects”映射的重写规则,请打开 Web 浏览器并请求以下任意 URL:

http://localhost/old-article
http://localhost/posts/default.aspx?id=1
http://localhost/old-title.html

上述任何一个 URL 都会导致浏览器重定向到 http://localhost/article.aspx?id=1

对查询字符串参数使用重写映射

重写映射的使用不局限于上述示例。 重写映射是键值对的泛型集合,可以在重写规则中的任何位置使用。 为了说明这一点,让我们创建一个可用于操作查询字符串参数的重写映射。

按照创建重写映射部分中所述的相同步骤创建第三个重写映射。 将重写映射命名为“IDtoTitleMap”并使用以下映射条目值:

原始值: 新值:
1 some-title-1
2 some-title-2
3 some-title-3

网站的 web.config 文件现在应包含以下两个重写映射:

<rewriteMaps>
    <rewriteMap name="StaticRewrites">
        <add key="/article1" value="/article.aspx?id=1&amp;title=some-title" />
        <add key="/some-title" value="/article.aspx?id=1&amp;title=some-title" />
        <add key="/post/some-title.html" value="/article.aspx?id=1&amp;title=some-title" />
    </rewriteMap>
    <rewriteMap name="StaticRedirects">
        <add key="/old-article.aspx?id=1" value="/article.aspx?id=1" />
        <add key="/posts/default.aspx?id=1" value="/article.aspx?id=1" />
        <add key="/old-title.html" value="/article.aspx?id=1" />
    </rewriteMap>
    <rewriteMap name="IDtoTitleMap">
        <add key="1" value="some-title-1" />
        <add key="2" value="some-title-2" />
        <add key="3" value="some-title-3" />
    </rewriteMap>
</rewriteMaps>

若要创建使用 IDtoTitleMap 重写映射的规则,请将以下规则定义复制并粘贴到网站的 web.config 文件中:

<rules>
    <rule name="Query String Rule" stopProcessing="true">
        <match url="^article\.aspx$" />
        <conditions>
            <add input="{QUERY_STRING}" pattern="(?:^|&)id=([0-9]+)(?:&|$)" />
            <add input="{IDtoTitleMap:{C:1}}" pattern="(.+)" />
        </conditions>
        <action type="Redirect" url="article.aspx?title={C:1}" appendQueryString="False" 
                                                            redirectType="Permanent" />
    </rule>
</rules>

让我们仔细查看每个规则元素以了解其作用:
<match url="^article\.aspx$" /> - 此元素告知 URL 重写模块在请求 article.aspx 文件时执行该规则。

<add input="{QUERY\_STRING}" pattern="(?:^|&amp;)id=([0-9]+)(?:&amp;|$)" /> - 此条件检查查询字符串是否包含采用数值的参数 id。 实际值在条件反向引用中捕获。 请注意,即使查询字符串包含其他参数,此模式也将起作用。

<add input="{IDtoTitleMap:{C:1}}" pattern="(.+)" /> - 此条件检查从重写映射 IDtoTitleMap 返回的值是否不是空字符串。 该条件使用前一个条件模式的反向引用作为重写映射的输入。

<action type="Redirect" url="article.aspx?title={C:1}" appendQueryString="False" redirectType="Permanent" /> - 此元素指定 URL 重写模块需要将 Web 客户端重定向回 Article.aspx 文件,但使用不同的查询字符串参数 title,该参数采用在重写映射中查找的值。

测试针对查询字符串的规则

若要测试使用“IDtoTitleMap”映射的重写规则,请打开 Web 浏览器并请求以下任意 URL:

http://localhost/article.aspx?id=1。 将重定向到 http://localhost/article.aspx?title=some-title-1. http://localhost/article.aspx?someparam=somevalue&id=2。 将重定向到 http://localhost/article.aspx?title=some-title-2

总结

在本演练中,你已了解如何使用重写映射来定义重写和重定向规则的 URL 映射。 此外,你还了解了如何使用重写映射来操作查询字符串参数。

当重写和重定向 URL 是静态的并且无法使用任何模式匹配技术来表达重写逻辑时,使用重写映射可以减少重写规则的数量。