Creating Rewrite Maps for Redirecting Old DasBlog URLs After Migration
Rewrite Maps in IIS
After successfully migrating the content from the old DasBlog site to the new DocPad based one, it was time to generate permanent redirects of old URLs to new ones, to keep inbound links working and not lose search rankings, once the new site goes live. Since the site is going to be hosted in Azure, I decided to use the URL Rewrite module - rewrite maps to be exact; because I need to map a large number of individual URLs, which can't be covered by a generic rule.
To avoid cluttering the web.config
file with all the mappings, I moved the rewrite maps into a separate file, keeping in web.config
only the rules and a reference to the external file:
<configuration>
<system.webServer>
<rewrite>
<rewriteMaps configSource="rewriteMaps.config" />
<rules>
<rule name="commentLinks">
<match url="^CommentView,guid,.+\.aspx$" />
<conditions>
<add input="{commentLinks:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false"
redirectType="Permanent" />
</rule>
<rule name="permalinks">
<match url=".+\.aspx$" />
<conditions>
<add input="{permalinks:{REQUEST_URI}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false"
redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
In the snippet above I have two rewrite rules for two rewrite maps. Matching their names; the first one takes care of GUID based comment pages, while the second one covers the article permalinks. Here's a valid snippet of rewriteMaps.config
file:
<rewriteMaps>
<rewriteMap name="permalinks">
<add key="/BookReviewSignalRRealtimeApplicationCookbook.aspx"
value="/blog/posts/20150626-BookReviewSignalRRealTimeApplicationCookbook.html"/>
<add key="/BookReviewMasteringTypeScript.aspx"
value="/blog/posts/20150615-BookReviewMasteringTypeScript.html"/>
</rewriteMap>
<rewriteMap name="commentLinks">
<add key="/CommentView,guid,50cee933-b7e1-4a15-99a4-a70b69d07dbd.aspx"
value="/blog/posts/20150626-BookReviewSignalRRealTimeApplicationCookbook.html"/>
<add key="/CommentView,guid,3fe215bf-3019-48fc-a765-bb4e3892fdd0.aspx"
value="/blog/posts/20150615-BookReviewMasteringTypeScript.html"/>
</rewriteMap>
</rewriteMaps>
As long as rewriteMaps
is the root element, and its children would be valid directly in web.config
, everything should work fine. Also notice that rewrite map names should match the input
attribute value in rule conditions.
Generating Rewrite Maps
Considering the large number of posts on my site, I had no intention of writing the rewrite maps by hand. Instead, I took advantage of the BlogML export of DasBlog content which I already used to convert the posts to the new format. Of course I also used the same tooling: Grunt and CoffeeScript. I just added the rewrite map generation to the conversion process.
First, I created two associative arrays with the URL mappings:
exportRewriteMaps = (posts) ->
fs = require 'fs'
moment = require 'moment'
slug = require 'slug'
titleCase = require 'title-case'
permalinkMappings = {}
commentLinkMappings = {}
for post in posts
newUrl = moment(post.$['date-created']).format('YYYYMMDD') + '-' +
slug(titleCase(post.title[0]._), '') + '.html'
permalinkMappings[post.$['post-url'].replace('http://www.damirscorner.com/', '')] = newUrl
commentLinkMappings['CommentView,guid,' + post.$['id'] + '.aspx'] = newUrl
The posts
argument matches the post collection I used for conversion. Of course, I generate newUrl
the same way I generated the filename for converted blog posts, with the omission of .md
extension which is removed by DocPad when generating the site. Post permalinks are stored in post-url
attribute; I just make them relative by removing the hostname part. I recreate the comment links in the code; I use id
attribute which contains the post GUID.
Now I had everything I needed to export the rewrite maps to a file:
xmlBuilder = require 'xmlbuilder'
root = xmlBuilder.create('rewriteMaps')
createRewriteMap 'permalinks', permalinkMappings, root
createRewriteMap 'commentLinks', commentLinkMappings, root
fs.writeFileSync 'rewriteMaps.config', root.end { pretty: true }
I use the xmlbuilder-js package. I create the required rewriteMaps
root element and pass it to the createRewriteMap
function which generates the rewriteMap
element corresponding to the other function arguments. In the end I dump everything into the destination file. The missing function is pretty straightforward:
createRewriteMap = (name, mappings, root) ->
map = root.ele('rewriteMap',
name: name)
map.ele('add',
key: '/' + key
value: '/blog/posts/' + value) for key, value of mappings
The only part worth mentioning, is the correct folder prefix that's added to generated new post file names. The resulting file using the above code can be directly used by IIS. Just before switching to the new site I can only regenerate it to include to the new blog posts written in the interim.