URL Rewrite module; Basic Understanding of rule
This article explains how <match/>, <conditions/> and <action/> work together in URL Rewrite module, and how they are defined in URL Rewrite module schema; rewrite_schema.xml.
Prerequisite: It is better to read these walkthrough for this blog.
http://learn.iis.net/page.aspx/461/creating-rewrite-rules-for-url-rewrite-module/
http://learn.iis.net/page.aspx/468/using-global-and-distributed-rewrite-rules/
In short, URL Rewrite performs <action/> with a given input url based on < match /> and <conditions/> defined in configuration.
· < match /> examines whether input url is matched against pattern.
· Once <rule/> is matched, the module examines <conditions/> to see whether they are satisfied.
· If <conditions/> is satisfied, then finally <action/> is performed.
Those <match/>, <conditions/> and <action/> are child elements of <rules/> and <globalRules/>.
Figure 1. Relationship among <rules/>, <rule/>, <match/>, <conditions/>, <action/>
Figure 1 illustrates relationship and cardinality among elements. <rules/> can have zero or many <rule/>, and <rule/> has <match/>, <action/> and optional zero or many <conditions/>
Let us see actual configuration examples. The examples used in this article should be defined in site root web.config. Note that I recommend you to use UI to set configuration.
<rewrite>
<rules>
<rule name="Ex01">
<match url="(.+)\.htm$" />
<action type="Rewrite" url="{R:1}.html" />
</rule>
</rules>
</rewrite>
Example 1. The simplest rule
Example 1 illustrates one simple rule which rewrites url with extension htm to html. In this example, <rules/> defines only one <rule/> without <conditions/>, which means it performs <action/> Rewrites if url’s file extension is .htm.
<rewrite>
<rules>
<rule name="Ex01">
<match url="(.+)\.htm$" />
<conditions>
<add input="{HTTP_HOST}" pattern="localhost" />
</conditions>
<action type="Rewrite" url="{R:1}.html" />
</rule>
</rules>
</rewrite>
Example 2. <rule/> with one condition
Example 2 adds one condition in <rule/>, where <conditions/> check whether the host name is “localhost” in order to perform <action/> Rewrite. The <rule/> Ex01 first tries pattern-<match> against input URL, and if matched, then evaluates <conditions/>. If they are satisfied, then rewrites URL.
<rewrite>
<rules>
<rule name="Ex01">
<match url="(.+)\.htm$" />
<conditions>
<add input="{HTTP_HOST}" pattern="localhost" />
<add input="{HTTP_PORT}" pattern="80" />
</conditions>
<action type="Rewrite" url="{R:1}.html" />
</rule>
</rules>
</rewrite>
Example 3 <rule/> with two conditions
Example 3 adds one more condition in <rule/>. Now, the rule “Ex01” checks whether input URL has “.htm” extension, and host is “localhsot” and port is 80. If matched and satisfied conditions, an input URL’s extension is rewritten to “.html”.
As Figure 1 illustrates, <rule/> can have zero or many conditions. In schema term, <conditions/> is a child element of <rule/> and has <collection/> element which you can <add/> one or more condition.
One useful attribute you can set in <conditions/> is “logicalGrouping” which has enum value; MatchAll or MatchAny. As name implies, you can apply logical AND or OR operator on conditions. The default value is MatchAll. So, Example 3 enforces both condition should be satisfied. If tweaked Example 3 with <conditions logicalGrouping =”MatchAny”> … </conditions>, then only one of conditions needs to be met to perform <action/>.
<rewrite>
<rules>
<rule name="Ex01">
<match url="(.+)\.htm$" />
<conditions>
<add input="{HTTP_HOST}" pattern="localhost" />
<add input="{SERVER_PORT}" pattern="80" />
</conditions>
<action type="Rewrite" url="{R:1}.html" />
</rule>
<rule name="Ex02">
<match url="^(hello)" />
<action type="Rewrite" url="{R:1}.txt" />
</rule>
</rules>
</rewrite>
Example 4. Multiple <rule/>
You can define multiple <rule/> in <rules/> since <rule/> is a child collection element of <rules/>. This is the same concept as the <rule/> and <conditions/>. One important thing here is that the rewritten URL from the current <rule/> will be an input URL for next <rule/>. In other words, they are chained together(just like singly linked list); the output of current <rule/> will become input of next <rule/>. But, if a URL were not rewritten, then the original URL will still be an input of the next rule.
Let us clarify this with an example under the configuration Example 4.
If GET /hello.htm is requested on localhost with port 80, the server will respond /hello.txt; since both <rule/>s are evaluated TRUE, <rule/> Ex01 rewrites hello.htm to hello.html, and then <rule/> Ex02 rewrites hello.html to hello.txt which will be a final resource to serve to a client. Figure 2.1 illustrates this.
Figure 2. 2.1) Both <rule/> are evaluated TRUE, 2,2) The second <rule/> is evaluated TRUE, 2.3) The first <rule/> is evaluated TRUE
However, if GET /hello.xml is requested on the same server, then it will still respond hello.txt, but in this case the first <rule/> Ex01 is evaluated FALSE, so the original URL will still be an input of the second <rule/> Ex02. Figure 2.2 illustrates this.
One more, if GET /world.html is requested, then it will serve /world.html since the only the first <rule/> Ex01 is evaluated TRUE. Figure 2.3 illustrates this.
There is one interesting attribute you can set at <rule/>; “stopProcessing” which is Boolean type (by default false). As the name suggests, it stops rule chaining process at current <rule/> to serve the currently rewritten url only if <rule/> were evaluated TRUE. For example, If we set <rule name="Ex01" stopProcessing=”true” >… </rule>, then request GET /hello.htm will serve /hello.html bypassing the second <rule/> Ex02.
In summary,
· <rule/>is evaluated TRUE if pattern-<match>ed and <conditions/> are satisfied if exists.
· <action/> is performed (Rewrite or Redirect) only if <rule/> is evaluated TRUE.
· Conditions can be OR/AND-operated depending on logicalGrouping attribute in <conditions/>
· <rules/> can define zero or many <rule/> which are chained.
· Input URL is changed during <rule/> chain; Current output becomes input of next rule.
· Rule chain can be broken out if <rule/> is evaluated TRUE and stopProcessing=”true”.
Hope it helps to understand the URL Rewrite module.