功能概述
URL 重写模块将请求 URL 重写为简单、用户友好和搜索引擎友好的地址,这些地址会显示给用户或在 Web 应用程序中使用。URL 重写使用定义的规则来评估并映射请求 URL,然后在由 IIS Web 服务器处理之前将其映射到规则中定义的地址。您可以定义包含正则表达式和通配符的 URL 重写逻辑,并且可以根据请求 URL、HTTP 头和服务器变量来应用规则。模块的主要用途是将请求 URL 重写为更友好的 URL,但您也可以使用该模块来定义执行重定向、发送自定义响应或中止请求的规则。
重写规则概述
重写规则定义了请求URL与什么进行比较或匹配,以及如果比较成功后应采取什么操作。
重写规则包括以下部分:
- 模式 – 规则模式用于指定正则表达式或用于匹配URL字符串的通配符模式。
- 条件 – 可选的条件集合用于在URL字符串匹配规则模式时指定额外的逻辑操作。在条件中,您可以检查HTTP头或服务器变量的特定值,或者验证请求的URL是否对应于物理文件系统中的文件或目录。
- 动作 – 动作用于指定如果URL字符串匹配规则模式并且所有规则条件都满足时要执行的操作。
重写规则作用域
重写规则可以定义在两个不同的集合中:
<globalRules>
– 此集合中的规则只能在服务器级别定义。全局规则用于定义服务器范围的URL重写逻辑。这些规则在ApplicationHost.config文件中定义,且不能在任何较低的配置级别被覆盖或禁用。全局规则始终在IIS请求处理管道的早期(PreBeginRequest事件)操作绝对URL的路径(即不包含服务器名称的请求URI)。这些规则在IIS请求处理管道的早期阶段进行评估(PreBeginRequest事件)。<rules>
– 此集合中的规则称为分布式规则,它们可以在配置层次结构中的任何级别定义。分布式规则用于定义特定配置范围的URL重写逻辑。通过使用Web.config文件,或在ApplicationHost.config或Web.config文件中使用<location>
标签,可以在任何配置级别添加这种类型的规则。分布式规则在定义它们的Web.config文件位置相对的URL路径上操作。在分布式规则定义在<location>
标签内部的情况下,它们在相对于该<location>
标签指定的路径的URL路径上操作。这些规则在IIS管道的BeginRequest事件中进行评估。
规则评估
IIS中的每个配置级别都可以定义零个或多个重写规则。规则按照指定的顺序进行评估。URL重写模块使用以下算法处理规则集:
- 首先,URL 与规则的模式进行匹配。如果匹配不成功,URL 重写模块会立即停止处理该规则,并继续处理下一个规则。
- 如果模式匹配并且没有该规则的条件,URL 重写模块将执行为此规则指定的操作,然后转到下一个规则,在该规则中使用替换后的 URL 作为输入。
- 如果模式匹配并且有规则的条件,URL 重写模块将评估这些条件。如果评估成功,将执行指定的规则操作,然后将重写后的 URL 作为输入传递给后续规则。
规则可能具有停止处理标志。当规则操作执行(即规则匹配)并且此标志打开时,这意味着将不再处理后续规则,并且请求将传递给IIS请求管道。默认情况下,此标志是关闭的。
规则继承
如果在多个配置级别上定义了规则,URL 重写模块将按以下顺序评估规则:
- 评估所有全局规则。
- 评估一个规则集,该规则集包括来自父配置级别和当前配置级别的分布式规则。评估按从父到子的顺序进行,这意味着父规则首先被评估,而最后子级别定义的规则最后被评估。
保留原始网址
URL 重写模块在以下服务器变量中保留原始请求的 URL 路径:
- HTTP_X_ORIGINAL_URL – 此服务器变量包含原始URL的解码格式;
- UNENCODED_URL – 此服务器变量包含Web客户端请求的原始URL,所有原始编码均得以保留。
从重写规则访问URL部分
理解如何从重写规则中访问URL字符串的某些部分是很重要的。
对于这种形式的HTTP URL:http(s)://
- <path> 与规则的模式进行匹配。
- <querystring> 可以在名为 QUERY_STRING 的服务器变量中找到,并且可以通过在规则中使用条件来访问。
- <host> 可以在服务器变量 HTTP_HOST 中找到,并且可以通过在规则中使用条件来访问。
- <port> 可以在服务器变量 SERVER_PORT 中获取,并且可以在规则中使用条件进行访问。
- 服务器变量 SERVER_PORT_SECURE 和 HTTPS 可以用来判断是否使用了安全连接。这些服务器变量可以通过在规则中使用条件来访问。
- 服务器变量REQUEST_URI可以用来访问整个请求的URL路径,包括查询字符串。
例如,如果请求了这个URL:http://www.mysite.com/content/default.aspx?tabid=2&subtabid=3
,并且在站点级别定义了一个重写规则,那么:
- 规则模式获取URL字符串
content/default.aspx
作为输入。 - QUERY_STRING 服务器变量包含
tabid=2&subtabid=3
. - HTTP_HOST 服务器变量包含
www.mysite.com
. - SERVER_PORT 服务器变量包含
80
. - SERVER_PORT_SECURE 服务器变量包含
0
和 HTTPS 包含OFF
. - REQUEST_URI 服务器变量包含
/content/default.aspx?tabid=2&subtabid=3
. - PATH_INFO 服务器变量包含
/content/default.aspx
.
请注意,传递给分布式规则的输入URL字符串始终相对于定义规则的Web.config文件的位置。例如,如果请求是http://www.mysite.com/content/default.aspx?tabid=2&subtabid=3
,并且在/content目录中定义了一个重写规则,那么规则将此URL字符串default.aspx作为输入。
重写规则配置
规则模式
重写规则模式用于指定与当前URL路径进行比较的模式。当前在此上下文中指的是规则应用时URL路径的值。如果之前有任何规则,它们可能会匹配原始请求的URL并进行修改。用于模式评估的URL字符串不包括查询字符串。要将查询字符串包含在规则评估中,您可以在规则的条件中使用QUERY_STRING服务器变量。有关更多信息,请参阅“在重写规则中使用服务器变量”。
在重写规则的 <match> 元素中指定一个模式。
规则模式语法
规则模式语法可以通过使用patternSyntax属性来指定规则。该属性可以设置为以下选项之一:
ECMAScript – 与 Perl 兼容(符合 ECMAScript 标准)的正则表达式语法。这是任何规则的默认选项。这是模式格式的示例:“^([_0-9a-zA-Z-]+/)?(wp-.*)"
通配符 – 通配符 在 IIS HTTP 重定向模块中使用的语法。以下是一个此格式的模式示例:“/Scripts/*_in.???”,其中星号(“*”)表示“匹配任意数量的任何字符并将其捕获到一个反向引用中”,而“?”表示匹配恰好一个字符(不会创建反向引用)。
该模式语法属性是按规则定义的,这意味着它适用于当前规则的模式以及该规则条件中使用的所有模式。
规则模式属性
可以通过使用negate属性来否定模式。当使用此属性时,规则动作仅在当前URL不匹配指定模式时执行。
默认情况下,使用不区分大小写的模式匹配。要启用区分大小写,您可以使用规则的matchCondition元素的ignoreCase属性。
规则条件
规则条件允许为规则评估定义附加逻辑,该逻辑可以基于除了当前URL字符串之外的其他输入。规则可以有零个或多个条件。规则条件在规则模式匹配成功后进行评估。
条件在重写规则的 <conditions> 集合中定义。此集合有一个名为 logicalGrouping 的属性,用于控制条件的评估方式。如果规则有条件,那么只有在规则模式匹配并且:
- 如果使用了logicalGrouping="MatchAll",则所有条件均被评估为真。
- 如果logicalGrouping="MatchAny" 被使用,则至少有一个条件被评估为真。
条件通过指定以下属性来定义:
- 输入字符串
- 比赛类型
条件输入指定用于条件评估的输入项。条件输入是一个任意字符串,可以包含服务器变量和/或到先前条件模式和/或到规则模式的后向引用。
比赛类型可以是以下三种选项之一:
-
IsFile – 此匹配类型用于确定输入字符串是否包含文件系统中文件的物理路径。如果未指定条件输入字符串,URL 重写模块将使用请求文件的物理路径作为条件输入的默认值。此匹配类型只能用于分布式规则。
-
IsDirectory – 此匹配类型用于确定输入字符串是否包含文件系统中目录的物理路径。如果未指定条件输入字符串,URL 重写模块将请求文件的物理路径用作条件输入的默认值。此匹配类型只能用于分布式规则。
-
模式 – 此匹配类型用于表示将任意输入字符串与正则表达式模式进行匹配的情况。条件模式可以通过使用正则表达式语法或通配符语法来指定。在条件中使用哪种模式取决于该条件所属规则的模式语法标志的值。此条件类型有两个相关的属性,用于控制模式匹配:
- 模式 – 使用此属性指定实际的模式。
- 忽略大小写 – 使用此属性来控制条件的模式匹配是否区分大小写。
此外,可以通过使用negate属性来否定条件评估的结果。这可以用来指定一个检查请求的URL是否不是文件的条件,如以下示例所示:
<add input="{REQUEST_FILENAME}" matchType="isFile" negate="true">
规则操作
当当前URL与规则模式匹配并且条件评估成功时(取决于规则配置,所有条件匹配或任意一个或多个条件匹配),将执行重写规则操作。有几种类型的的操作可供选择,<action>配置元素的type属性可以用来指定规则执行的操作。以下章节描述了不同操作类型和与特定操作类型相关的配置选项。
重写操作
一个 重写 操作将当前的 URL 字符串替换为一个替换字符串。替换字符串必须始终指定 URL 路径(例如,contoso/test/default.aspx)。请注意,包含文件系统物理路径的替换(例如,C:\inetpub\wwwroot
)在 IIS 中不受支持。
一个重写操作有以下配置选项:
-
url – 这是用于重写当前URL的替换字符串。替换URL是一个字符串值,可以包含以下内容:
- 对条件和规则模式的后向引用。(有关更多信息,请参阅有关如何使用后向引用的部分。)
- 服务器变量。(有关更多信息,请参阅有关如何使用服务器变量的部分。)
-
appendQueryString – 指定在替换期间是否保留当前 URL 的查询字符串。默认情况下,如果未指定appendQueryString 标志的值,则假定其为 TRUE。这意味着原始 URL 的查询字符串将附加到替换后的 URL。
重定向操作
一个重定向操作指示URL重写模块向客户端发送重定向响应。可以将重定向状态码(3xx)作为此操作的参数指定。响应的Location字段包含在规则中指定的替换字符串。
重定向规则的替换 URL 可以指定为以下形式之一:
- 相对URL路径 – contoso/test/default.aspx
- 绝对URI –
https://example.com/contoso/test/default.aspx
使用重定向操作意味着在重定向执行后,当前URL不再评估后续规则。
一个重定向操作有以下配置选项:
-
url – 使用替换字符串作为重定向URL。替换URL是一个可以包含以下内容的字符串:
- 对条件和规则模式的后向引用。(有关更多信息,请参阅有关如何使用后向引用的部分。)
- 服务器变量。(有关更多信息,请参阅有关如何使用服务器变量的部分。)
-
appendQueryString – 指定是否在替换过程中保留当前 URL 的查询字符串。默认情况下,如果未指定AppendQueryString 标志,则假定为 TRUE。这意味着将原始 URL 的查询字符串附加到替换后的 URL。
-
redirectType – 指定重定向时使用的状态码:
- 301 – 永久
- 302 – 找到
- 303 – 查看其他
- 307 – 临时
笔记
HTTP 状态码 308(永久重定向)不被 URL 重写模块支持。
自定义响应操作
一个 CustomResponse 动作使URL重写模块通过使用用户指定的状态码、子码和原因来响应HTTP客户端。使用 CustomResponse 动作意味着在执行此操作后,当前URL不再评估任何后续规则。
CustomResponse 动作有以下配置选项:
- statusCode– 指定要返回给客户端的的状态码。
- 子状态代码 – 指定用于响应客户端的子状态代码。
- statusReason – 指定与状态码一起使用的理由短语。
- statusDescription – 指定要放在响应主体中的单行描述。
中止请求操作
中止请求 动作导致URL重写模块终止当前请求的HTTP连接。该动作没有参数。使用此动作意味着在执行此动作后,当前URL不再评估任何后续规则。
无操作
一个无操作用于指定不执行任何操作。
在重写规则中使用服务器变量
服务器变量提供了有关当前HTTP请求的附加信息。您可以使用此信息来做出重写决策或构造重写后的URL。服务器变量可以在重写规则中的以下位置引用:
-
在条件输入字符串
-
在规则替换字符串中,具体:
- url 重写和重定向操作的属性
- 状态行 和 响应行 的 自定义响应 动作
服务器变量可以通过使用{VARIABLE_NAME}语法来引用。例如,以下条件使用了QUERY_STRING服务器变量:
<add input="{QUERY_STRING}" pattern="id=([0-9]+)" />
服务器变量也可以用来访问当前请求的HTTP头。当前请求提供的任何HTTP头都表示为一个服务器变量,其名称根据以下命名约定生成:
- HTTP头名称中的所有短划线("-")符号都转换为下划线符号("_")。
- HTTP头名称中的所有字母都转换为大写。
- "HTTP_" 前缀被添加到头名称。
例如,为了在重写规则中访问HTTP头“user-agent”,您可以使用{HTTP_USER_AGENT}服务器变量。
在重写规则中使用反向引用
规则或条件输入的一部分可以被捕获到后引用中。这些后引用可以随后在规则操作中用于构建替换URL,或在规则条件中用于构建输入字符串。
反向引用根据所使用的模式语法以不同的方式生成。当使用ECMAScript模式语法时,可以通过在必须捕获反向引用的模式部分周围添加括号来创建反向引用。例如,模式([0-9]+)/([a-z]+).html将捕获07和article,从这个请求的URL中创建反向引用: 07/article.html。当使用“通配符”模式语法时,如果模式中使用了星号(*),则总是创建反向引用。如果模式中使用了“?”,则不会创建反向引用。例如,模式*/*.html将捕获contoso和test 在此请求的URL中的反向引用:contoso/test.html.
无论使用哪种模式语法捕获回参引用,其使用方式都是一样的。回参引用可以在重写规则中的以下位置使用:
-
在条件输入字符串
-
在规则操作中,具体来说:
- url 重写和重定向操作的属性
- 状态行 和 响应行 的 自定义响应 动作
-
在重写映射的关键参数
对条件模式的后向引用通过{C:N}来识别,其中N从0到9。对规则模式的后向引用通过{R:N}来识别,其中N从0到9。请注意,对于这两种类型的后向引用,{R:0}和{C:0}将包含匹配的字符串。
例如,在这个模式中:
^(www\.)(.*)$
对于字符串:www.foo.com
后引用将按如下方式索引:
{C:0} - www.foo.com
{C:1} - www.
{C:2} - foo.com
在一个规则动作中,您可以在规则模式和该规则的上一个匹配条件中使用后向引用。在条件输入字符串中,您可以使用规则模式和之前匹配的条件的后向引用。
以下规则示例演示了如何创建和引用回溯引用:
<rule name="Rewrite subdomain">
<match url="^(.+)" /> <!-- rule back-reference is captured here -->
<conditions>
<add input="{HTTP_HOST}" type="Pattern" pattern="^([^.]+)\.mysite\.com$" /> <!-- condition back-reference is captured here -->
</conditions>
<action type="Rewrite" url="{C:1}/{R:1}" /> <!-- rewrite action uses back-references to condition and to rule when rewriting the url -->
</rule>
与IIS输出缓存的交互
URL 重写模块控制 IIS 输出缓存行为,以实现以下目的:
- 优化使用重写URL的内核模式和用户模式响应输出缓存,从而提高使用URL重写模块的Web应用程序的性能。
- 在URL重写可能导致缓存逻辑被违反时,防止响应的缓存。
该模块通过更改某些缓存属性或完全禁用缓存来控制输出缓存。如果IIS配置或IIS管道中的任何其他模块已禁用输出缓存,则该模块无法启用输出缓存。输出缓存的控制如下:
-
该模块始终将用户模式缓存设置为varyByHeader="HTTP_X_ORIGINAL_URL"。这确保了当启用用户模式缓存时,模块会考虑到原始URL来构造缓存条目的键。
-
如果重写规则集使用了在整个进程生命周期中保持恒定或从请求的URL派生的服务器变量,该规则集被认为是安全的,可以用于输出缓存。这意味着URL重写模块将不会以任何方式更改现有的缓存策略,除了设置varyByHeader,如在步骤1中所述。
以下服务器变量在使用在重写规则中时,不会对输出缓存策略产生任何影响:
- "缓存链接"
- "DOCUMENT_ROOT"
- "HTTP_URL"
- "HTTP_HOST"
- "PATH_INFO"
- "路径翻译"
- "QUERY_STRING"
- "REQUEST_FILENAME"
- "REQUEST_URI"
- "SCRIPT_FILENAME"
- "脚本名称"
- 脚本已翻译
- "未编码的网址"
- "网址"
- "URL_PATH_INFO"
- "APP_POOL_ID"
- "APPL_MD_PATH"
- "APPL_PHYSICAL_PATH"
- "网关接口"
- "服务器软件"
- "SSI_EXEC_DISABLED"
-
如果重写规则集使用了上述列表中未提及的任何服务器变量,则该规则集被认为对输出缓存不安全。这意味着,无论请求URL是否被重写,URL重写模块将禁用所有请求的内核模式缓存。此外,模块将通过设置缓存属性varyByValue来更改用户模式缓存的缓存策略,使其包含规则集中使用的所有服务器变量值的连接字符串。
字符串函数
有三个字符串函数可以用于更改重写规则动作以及任何条件中的值:
- ToLower - 返回输入字符串的小写形式。
- UrlEncode - 返回输入字符串转换为URL编码格式。此函数在重写规则中的替换URL包含特殊字符(例如非ASCII或URI不安全字符)时使用。
- UrlDecode - 解码URL编码的输入字符串。此函数可用于在将条件输入与模式匹配之前进行解码。
可以使用以下语法调用这些函数:
{function_name:any_string}
“function_name”可以是以下之一:“ToLower”、“UrlEncode”、“UrlDecode”。"Any_string"可以是文字字符串或由服务器变量或回参构建的字符串。例如,以下字符串函数调用是有效的:
{ToLower:DEFAULT.HTM}
{UrlDecode:{REQUEST_URI}}
{UrlEncode:{R:1}.aspx?p=[résumé]}
字符串函数可以在以下位置用于重写规则中:
-
在条件输入字符串
-
在规则替换字符串中,具体:
- url 属性 重写 和 重定向 操作
- 状态行 和 响应行 属性的 自定义响应 动作
一个使用ToLower函数的规则示例:
<rule name="Redirect to canonical url">
<match url="^(.+)" /> <!-- rule back-reference is captured here -->
<conditions>
<!-- Check whether the requested domain is in canonical form -->
<add input="{HTTP_HOST}" type="Pattern" pattern="^www\.mysite\.com$" negate="true" />
</conditions>
<!-- Redirect to canonical url and convert URL path to lowercase -->
<action type="Redirect" url="http://www.mysite.com/{ToLower:{R:1}}" redirectType="Found" />
</rule>
一个使用UrlEncode函数的规则示例:
<rules>
<rule name="UrlEncode example" stopProcessing="true">
<match url="resume" />
<action type="Rewrite" url="default.aspx?name={UrlEncode:résumé}"/>
</rule>
一个使用UrlDecode函数的规则示例:
<rules>
<rule name="UrlDecode example">
<match url="default.aspx" />
<conditions>
<add input="{UrlDecode:{QUERY_STRING}}" pattern="résumé" />
</conditions>
<action type="Rewrite" url="default.aspx?type=resume" />
</rule>
</rules>
重写地图
重写映射是一组任意名称-值对集合,可以在重写规则中使用,以在重写过程中生成替换URL。重写映射在你有一大组重写规则,并且所有这些规则都使用静态字符串时特别有用(即,当没有使用模式匹配时)。在这些情况下,与其定义一大组简单的重写规则,不如将所有映射放入重写映射中,作为键和值在输入URL和替换URL之间。然后,为了根据输入URL查找替换URL,你将有一个引用重写映射的重写规则。
重写映射定义了一个命名的名称-值对字符串集合,如下例所示:
<rewriteMap name="MyRewriteMap" defaultValue="">
<add key="a.html" value="b.html" />
<add key="c.aspx" value="d.aspx" />
<add key="e.php" value="f.php" />
</rewriteMap>
重写映射通过其名称唯一标识,并且可以包含零个或多个键值对。此外,重写映射可以指定当未找到键时使用的默认值。这通过使用defaultValue属性进行控制。默认情况下,使用空字符串作为默认值。
在任何配置级别上都可以有任意数量的重写映射,除了文件级别。重写映射位于<rewriteMaps>集合元素内。
重写映射通过以下语法在重写规则中进行引用:
{RewriteMapName:Key}
键参数可以是任何任意字符串,并且可以包含对规则或条件模式的反向引用。例如,以下是一些有效的重写映射使用示例:
{MyRewriteMap:contoso/{R:1}/test/{C:1}}
{MyRewriteMap:a.html}
{MyRewriteMap:{R:1}?{C:1}&contoso=test}
在rewrite map引用中,对参数传递的键进行查找并用查找的值进行替换。如果未找到键,则使用该rewrite map的默认值。
在重写规则中,重写映射可以在以下位置引用:
-
在条件输入字符串
-
在规则替换字符串中,具体:
- url 属性 重写 和 重定向 操作
- 状态行 和 响应行 的 自定义响应 动作
示例 1:定义重写映射如下:
<rewrite>
<rewriteMaps>
<rewriteMap name="StaticRewrites" defaultValue="">
<add key="/diagnostics" value="/default.aspx?tabid=2&subtabid=29" />
<add key="/webcasts" value="/default.aspx?tabid=2&subtabid=24" />
<add key="/php" value="/default.aspx?tabid=7116" />
</rewriteMap>
</rewriteMaps>
</rewrite>
定义如下重写规则:
<rewrite>
<rule name="Rewrite Rule">
<match url=".*" />
<conditions>
<add input="{StaticRewrites:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Rewrite" url="{C:1}"/>
</rule>
</rewrite>
请求的URL /diagnostic 将被重写为 /default.aspx?tabid=2&subtabid=29.
请求的URL /webcasts 将被重写为 /default.aspx?tabid=2&subtabid=24.
请求的URL /php 将被重写为 /default.aspx?tabid=7116.
请求的URL /default.aspx 不会被重写,因为重写映射不包含键为"/default.aspx"的元素;因此重写映射将返回空字符串,这将不匹配条件模式,所以规则动作将不会执行。
示例 2:定义了一个重写映射如下:
<rewrite>
<rewriteMaps>
<rewriteMap name="StaticRedirects" defaultValue="">
<add key="/default.aspx?tabid=2&subtabid=29" value="/diagnostics" />
<add key="/default.aspx?tabid=2&subtabid=24" value="/webcasts" />
<add key="/default.aspx?tabid=7116" value="/php" />
</rewriteMap>
</rewriteMaps>
</rewrite>
定义如下重写规则:
<rewrite>
<rule name="Redirect rule">
<match url=".*" />
<conditions>
<add input="{StaticRedirects:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="http://www.contoso.com{C:1}" redirectType="Found" />
</rule>
</rewrite>
请求的URL /default.aspx?tabid=2&subtabid=29 将被重定向到 http://www.contoso.com/diagnostics
.
请求的URL /default.aspx?tabid=2&subtabid=24 将被重定向到 http://www.contoso.com/webcasts
.
请求的URL /default.aspx?tabid=7116 将被重定向到 http://www.contoso.com/php
.
请求的URL /default.aspx 不会被重定向,因为rewrite map不包含键为"/default.aspx"的元素;因此rewrite map将返回空字符串,这将不匹配条件模式,所以规则动作将不会执行。