URL Rewrite Rules used by WayneYe.com

I've successfully transferred my website to winhost, now the architecture is IIS 7.5 + ASP.NET 4.0 + SQL Server 2008 R2 + HTML5, this blog post is a summary about URL Rewrite Rules used by WayneYe.com.

RESTful URL for blogs

Blog posts are absolutely the soul of a blog website, comparing with blog URL format: "/yyyy/MM/{Blog_Title}", I actually prefer "/Blog/{Blog_Title}", more simpler/shorter, in additional and more important, generally speacking,valuable content is valuable no matter when it was posted, for example, a developer is searching C# covariance & contravariance articles, two articles separately posted on 3/28/2010 and 1/25/2011 won't make ANY difference for this developer.

Now that all my blogs take URI format like: "http://WayneYe.com/Blog/{Blog_Title}", it is so called "Permalink", I must ensure there is no duplicate blog titles (not case sensetive even if I can enable URL case sensitive through IIS manager, it would be quite confuse to the end user), so actually in my backend blog post page I did a DB check for existing blog titiles:)

Here is the Blog URL rewrite config XML stored in my Web.config:

 <rule name="BlogPermalinkRewrite">
    <match url="^Blog/([A-Za-z0-9-_()^%]{1,})$" />
    <action type="Rewrite" url="ViewBlog.aspx?Permalink={R:1}" />
</rule>

Navigate Links

That's so simply, rewrite to an ASPX page under a matched directory:

 <rule name="NaviAlbum" patternSyntax="ExactMatch">
    <match url="Album" />
    <action type="Rewrite" url="Album/Index.aspx" />
</rule>
<rule name="NaviVideo" patternSyntax="ExactMatch">
    <match url="Video" />
    <action type="Rewrite" url="Video/Index.aspx" />
</rule>
<rule name="NaviTags" patternSyntax="ExactMatch">
    <match url="Tags" />
    <action type="Rewrite" url="Tags/Index.aspx" />
</rule>
<rule name="NaviVisitRecord" patternSyntax="ExactMatch">
    <match url="VisitRecord" />
    <action type="Rewrite" url="VisitRecord/Index.aspx" />
</rule>
<rule name="NaviAboutMe" patternSyntax="ExactMatch">
    <match url="AboutMe" />
    <action type="Rewrite" url="AboutMe/Index.aspx" />
</rule>

Category/Archive/Tag

These three type of URLs are similar, but makes a log of sense to a website comforming REST.

 <rule name="CategoryRewrite">
    <match url="^Category/([A-Za-z0-9-_/]{1,})$" />
    <action type="Rewrite" url="ShowBlogs.aspx?Condition=Category&amp;Cat={R:1}" />
</rule>
<rule name="BlogTagRewrite">
    <match url="^Tag/(.*)$" />
    <action type="Rewrite" url="SearchTag.aspx?t={R:1}" />
</rule>
<rule name="ArchiveYearRewrite">
    <match url="^Archive/(\d{4})$" />
    <action type="Rewrite" url="ShowBlogs.aspx?Condition=Time&amp;Year={R:1}" />
</rule>
<rule name="ArchiveYearMonthRewrite">
    <match url="^Archive/(\d{4})/(\d{2})$" />
    <action type="Rewrite" url="ShowBlogs.aspx?Condition=Time&amp;Year={R:1}&amp;Month={R:2}" />
</rule>
<rule name="ArchiveYearMonthDayRewrite">
    <match url="^Archive/(\d{4})/(\d{2})/(\d{1,2})$" />
    <action type="Rewrite" url="ShowBlogs.aspx?Condition=Time&amp;Year={R:1}&amp;Month={R:2}&amp;Day={R:3}" />
</rule>

Define Atom/RSS feeds MIME type

WayneYe.com programmatically generates Atom/RSS feeds in plain XML format, the two XML file exists phisically under Feeds/Atom/Atom.xml and Feeds/RSS/RSS.xml, other then rewrite URL for both, one more important thing to do is override the "text/xml" MIME type to follow the standard:

  1. Atom feeds MIME type should be "application/atom+xml"
  2. RSS feeds MIME type should be "application/rss+xml".

To achieve this needs a little bit more work: intercepting response stream and overriding server variable, this requires adding an "Allowed Server Variables": this is done by the following steps:

  1. Open IIS Manager, go to my web application.
  2. Go to "URL Rewrite"
  3. In the Actions panel, select "View Server Variables".
  4. Add a new Server Variable: "RESPONSE_CONTENT_TYPE".

Here is the config XML for rewriting the request:

 <rule name="AtomFeedRewrite" patternSyntax="ExactMatch">
    <match url="Feeds/Atom" />
    <action type="Rewrite" url="Feeds/Atom/Atom.xml" />
</rule>
<rule name="RSSFeedRewrite" patternSyntax="ExactMatch">
    <match url="Feeds/RSS" />
    <action type="Rewrite" url="Feeds/RSS/RSS.xml" />
</rule>

And below is for overriding the "text/xml" MIME type config XML:

 <outboundRules>
    <preConditions>
        <preCondition name="Match Atom Feeds">
            <add input="{REQUEST_URI}" pattern="Feeds/Atom" />
        </preCondition>
        <preCondition name="Match RSS Feeds">
            <add input="{REQUEST_URI}" pattern="Feeds/RSS" />
        </preCondition>
    </preConditions>
    <rule name="AtomFeedsIMEType" preCondition="Match Atom Feeds">
        <match serverVariable="RESPONSE_CONTENT_TYPE" pattern="(.*)" negate="false" />
        <action type="Rewrite" value="application/atom+xml" replace="true" />
    </rule>
    <rule name="RSSFeedsIMEType" preCondition="Match RSS Feeds">
        <match serverVariable="RESPONSE_CONTENT_TYPE" pattern="(.*)" negate="false" />
        <action type="Rewrite" value="application/rss+xml" replace="true" />
    </rule>
</outboundRules>

Result:
Define Atom Feeds IME Type

 

Customize HTTP Response Headers

I added a customized (non-standard) "Auther" HTTP response Header for all the requests, just for fun^_^

The config code is below:

 <outboundRules>
    <rule name="WayneHttpHeader">
        <match serverVariable="RESPONSE_Author" pattern="^$" />
        <action type="Rewrite" value="Wayne Ye (Admin@WayneYe.com)" />
    </rule>
</outboundRules>

Screenshot for an example of "Auther" header appears when requesting to http://WayneYe.com/AboutMe.

Customized "Auther" Header

Canonical domain URL

Canonical domain URL is a crucial fact for a website which want to make good SEO, URL Rewrite module already provides a template to help you do this by simply giving it your preferred domain. I did and the result is showing below:

Conanical URL

Conclusion

IIS URL Rewrite Module is the most powerful rewriting tool in the world, simple, easy to learn and use, highly customization and extention supports, I love it! In fact before I transferred my blog from to winhost, to achieve few parts of the rewrite functions listed above, I wrote mroe than 100 hundred lines of code in HttpModule, and got seriously compromised results, let me record the miserable history below.

I defined an WayneBlogModule which inherits from IHttpModule, it add extra URL examination to HttpApplication.BeginRequest, checking whether the requested URI matches conditions defined by myself, based on concrete requested URI, the WayneBlogModule invoke HttpContext.RewritePath to achieve the goal, however, it has an inextricable issue: the requested resource "MUST exist", otherwise IIS will return 404 to the client, the module has no chance to get executed, although there are some tricky ways (or I'd say, odd ways) to solve this issue such as "let redirects all 404 response to a specified file" then checks the requested URI, I didn't adopt that because I think it is odd and obay the original technical base.

IIS URL Rewrite module perfectly solves my problem, sincerely thanks! 

Screenshot for completely list of rewrite rule used by WayneYe.com (click to enlarge):

Completely rule list

Further Reading

IIS URL Rewrite module

Download URL Rewrite Module 2.0

Tags:

Categories:

Updated:

Leave a comment