使用全局和分布式重写规则

作者:Ruslan Yakushev

本演练将介绍 URL 重写模块支持的不同类型的规则,并会指导你了解如何配置全局和分布式重写规则。

背景

全局重写规则用于定义服务器范围的 URL 重写逻辑。 这些规则在 applicationHost.config 文件中定义,无法在任何较低的配置级别(如网站或虚拟目录)上重写或禁用。 全局规则始终在绝对 URL 路径上运行(即没有服务器名称的请求 URI)。 例如,如果向 http://localhost/directory1/directory2/index.html 发送请求,则 URL 重写模块会将“directory1/directory2/index.html”作为输入传递给全局规则。

分布式规则用于定义特定于特定配置范围的 URL 重写逻辑。 可以使用 Web 配置文件在任何配置级别(文件除外)上定义分布式规则。 本地规则始终在 URL 上操作,相对于定义它们的 Web.config 文件的位置。 例如,如果对 http://localhost/directory1/directory2/index.html 发送请求且在位于 directory1 中的 Web 配置文件中定义了一条重写规则,则 URL 重写模块会将“directory2/index.html”作为输入传递给该规则。

始终首先评估全局规则集,然后会使用全局规则集生成的 URL 字符串评估分布式规则集。

先决条件

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

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

设置演练方案

为了演示如何使用全局和本地规则,我们将实现将子域映射到目录的常见方案。 这样,我们便能够使用子域访问站点上不同目录中的内容。 例如,用户将能够浏览到 http://blog.mysite.com 而不是 http://mysite.com/blog,或浏览到 http://forum.mysite.com 而不是 http://mysite.com/forum

若要设置此方案,请执行以下步骤:

  1. %SystemDrive%\inetpub\wwwroot\ 文件夹中创建两个文件夹,分别命名为“blog”和“forum”。

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

    <%@ 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>
          <p>This page is located in blog subdomain.</p>
          <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>
    
  3. 复制以下 asp.net 代码,并将其放入名为“forum.aspx”的文件中的 %SystemDrive%\inetpub\wwwroot\forum 文件夹中:

    <%@ 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>
          <p>This page is located in forum subdomain.</p>
          <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>
    
  4. 打开位于 %SystemDrive%\windows\system32\drivers\etc\ 的名为“hosts”的文件,在其中添加以下两行:

    127.0.0.1 forum_localhost
    127.0.0.1 blog_localhost
    

    添加这两行之后,打开 Web 浏览器并浏览到 http://blog_localhost/blog/article.aspx 和 http://forum_localhost/forum/forum.aspx,验证页面在浏览器中渲染得是否正确。

创建全局重写规则

首先,我们将创建一个全局重写规则,该规则基于主机头重写 URL。 例如,如果向 http://blog_localhost/article.aspx 发送请求,然后规则会将 URL 路径更改为“blog/article.aspx”。

若要在 IIS 管理器中使用 URL 重写 UI 创建全局规则,请执行以下步骤:

  1. 转到 IIS 管理器
  2. 在导航树视图中,选择服务器节点。
  3. 在功能视图中,单击“URL 重写模块”
    Screenshot of the WIN two K eight R T M home page. The U R L Rewrite icon is highlighted.
  4. 在“操作”窗格中,单击“添加规则…”
    Screenshot of the U R L Rewrite page. In the Actions pane Add Rules is highlighted.
  5. 在“添加规则”对话框中,选择“空白规则”,然后单击“确定”:
    Screenshot of the Add Rules dialog box. The Blank Rule icon is selected.

接下来,我们必须定义实际的重写规则。 在 URL 重写模块中,重写规则是通过指定四条基本信息来定义的:

  • 规则名称
  • 用于匹配 URL 字符串的模式
  • 一组可选条件
  • 当模式匹配并且所有条件检查都成功时要执行的操作

命名规则

在“名称”文本框中输入用于唯一标识规则的名称,例如:“子域映射”。

定义模式

在“模式”文本框中输入以下字符串:

(.*)

此字符串是一个正则表达式,其指定的模式会匹配任何 URL 字符串,包括空字符串,并将在反向引用中捕获匹配的字符串。

定义条件

单击“添加条件”按钮:

Screenshot of the Edit Rule page. In the Conditions category, Add Conditions is highlighted.

单击“添加...”按钮,显示用于定义条件的对话框的。

Screenshot of the Edit Rule page. The Add button in the Conditions category is highlighted.
在“条件输入:”,输入此字符串:“{HTTP_HOST}”。 这会配置 URL 重写模块将条件的输入用作 HTTP 请求主机头的值

在下拉列表组合框中,选择“匹配模式”。

在“模式”文本框中,输入"^([^_]+)_[^_]+"。 此正则表达式将用于匹配我们创建的域(blog_localhost 和 forum_localhost),并将在“_”符号之前捕获字符串的一部分作为后引用。 例如,对于字符串“blog_localhost”,它将在后引用中保留“blog”。

指定所有属性后,条件对话框应如下所示:

Screenshot of the Edit Condition dialog box. In the Condition input box the text bracket H T T P underscore HOST close bracket is written. The Ignore case checkbox is checked.

单击“确定”保存条件并返回到“添加规则”UI。

定义操作

由于要创建的规则应该重写 URL,因此请在“操作”组框中选择“重写”操作类型。 在“重写 URL”文本框中,输入以下字符串:

{C:1}/{R:1}

此字符串指定应重写输入 URL 的内容。 条件 {C:1} 的后引用用作文件夹的名称,然后无论在规则模式中捕获到什么内容都会使用后引用保留到规则 {R:1}。

保留所有其他设置的默认值。 “编辑规则”UI 应如以下页面所示:

Screenshot of the Edit Rule page. The Input, Type, and Pattern columns all have text.

单击右侧的“应用”操作保存规则。

若要了解如何应用此规则,让我们演练 HTTP 客户端请求此 URL 时 URL 重写模块执行的步骤:
http://blog_localhost/article.aspx?id=323

  1. URL 重写模块将“article.aspx?id=323”作为规则的输入 URL 传递给规则,成功将其与规则模式匹配,并在规则后引用 {R:1} 中捕获它
  2. 主机标头值(“blog_localhost”)已成功与正则表达式“^([^_]+)_[^_]+”匹配,结果“blog”在条件后引用 {C:1} 中捕获
  3. 根据替换字符串 {C:1}/{R:1},URL 被重写为“blog/article.aspx?id=323”。

测试规则

若要测试规则是否正确重写 URL,请打开 Internet 浏览器并请求以下 URL:
http://blog_localhost/article.aspx?id=123

Screenshot of the U R L Rewrite Module Test Page. The Server Variable information and the Value information is shown.

应会看到 URL 重写模块已更改 URL,并在“blog”目录中打开了Article.aspx页。 URL 重写模块所做的更改基于从主机头中提取的信息。

同样,当你请求 http://forum_localhost/forum.aspx?id=345 时,也会将 URL 重写为 /forum/forum.aspx?id=345

创建分布式规则

我们刚刚创建的全局规则用于根据从主机头提取的信息将请求映射到文件夹。 现在,我们将创建分布式规则,允许在没有查询字符串参数的情况下具有 URL。 分布式规则将作为 URL 的输入,该 URL 已由全局规则修改,并将对其执行其他修改。 具体而言:

  • “blog”文件夹中的重写规则将重写 URL 路径,从“article/234/some-title”重写为“article.aspx?id=234&title=some-title”
  • “forum”文件夹中的重写规则会将 URL 路径从“topic/123/some-topic-title”重写为“forum.aspx?topic=some-topic-title&id=123”

可以通过使用 IIS 管理器或编辑 web.config 文件来创建本地规则。 出于演示目的,我们将通过手动编辑 web.config 文件来创建规则。

若要创建分布式重写规则,请执行以下操作:

  1. %SystemDrive%\inetpub\wwwroot\**blog** 文件夹中创建一个空的 web.config 文件。 在文本编辑器中打开文件,然后将以下 XML 代码粘贴到其中:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
      <system.webServer>
        <rewrite>
          <rules>
            <rule name="Rewrite to article.aspx">
              <match url="^article/([0-9]+)/([_0-9a-z-]+)"/>
              <action type="Rewrite" url="article.aspx?id={R:1}&amp;title={R:2}"/>
            </rule>
          </rules>
        </rewrite>
      </system.webServer>
    </configuration>
    
  2. %SystemDrive%\inetpub\wwwroot\**forum** 文件夹中创建一个空的 web.config 文件。 在文本编辑器中打开文件,然后将以下 XML 代码粘贴到其中:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
      <system.webServer>
        <rewrite>
          <rules>
            <rule name="Rewrite to forum.aspx">
              <match url="^topic/([0-9]+)/([_0-9a-z-]+)"/>
              <action type="Rewrite" url="forum.aspx?topic={R:2}&amp;id={R:1}"/>
            </rule>
          </rules>
        </rewrite>
      </system.webServer>
    </configuration>
    

测试全局规则和分布式规则

若要一起测试所有规则是否正常工作,请打开 Web 浏览器并向 http://blog_localhost/article/234/some-title 发出请求。 浏览器中的响应应指示 URL 首先由全局规则更改,然后由分布式规则进行额外修改。

同样,如果请求 http://forum_localhost/topic/123/some-topic-title,应会看到 URL 重写模块将请求的 URL 字符串更改为“/forum/forum.aspx?topic=some-topic-title&id=123.”

Screenshot of the U R L Rewrite Module Test Page. The U R L string has changed.

总结

在本教程中,你已使用全局规则实现了子域映射方案,然后使用分布式规则为这些文件夹中的网页启用用户友好 URL。