I recently started using Twitter, and noticed that a lot of folks (myself included) like to use URL shortening services when posting a Tweet. Since Twitter only lets you post Tweets 140-characters or shorter, services like bit.ly, tinyurl.com, and twurl.cc are critical when you want to Tweet a page with a long URL (like this blog post). Just for fun, I started to look into how these URL shortening services work. After a few minutes, I decided I wanted to make my own (a tinyurl.com, bit.ly, twurl.cc clone). Not surprisingly, it's absolutely trivial to make your own URL alias service using Apache's mod_rewrite.FOLLOWUP 3/21/09: There's a better way to do this, as I described here.
<VirtualHost *:80>
DocumentRoot /my/server/root/kolich.cc/
ServerName www.kolich.cc
ServerAlias kolich.cc
ServerAdmin support@example.com
RewriteEngine On
RewriteMap tinyurlmap txt:/my/server/root/kolich.cc/map.txt
RewriteRule ^/(.*)$ ${tinyurlmap:$1|http://mark.koli.ch} [R=301,L]
ErrorLog logs/kolich.cc-error_log
CustomLog logs/kolich.cc-access_log combined
</VirtualHost>
The parts of this VirtualHost configuration we really care about are the RewriteMap and RewriteRule directives. The RewriteMap maps a list of request URI's to full URL's (example below). The RewriteRule defines how to process the map defined by the RewriteMap.
The map file itself, map.txt, is extremely simple. Again, it simply maps a URI to a full URL. Here are a few examples:
xs34a6 http://kolich.com
kljhd7 http://www.google.com
u345nm http://mark.koli.ch/2009/02/somepost.html
So, using these examples if you visit kolich.cc/xs34a6, mod_rewrite will redirect you to http://kolich.com. If you visit kolich.cc/u345nm then you'll get forwarded to ...somepost.html, and so on. NOTE: You don't have to restart Apache when you make changes to your map file. The mod_rewrite module will read it for you on the fly.
Finally, the RewriteRule part is where the magic happens. It takes the URI and runs it through the rewrite map defined by "tinyurlmap". If it finds a match, it will send a HTTP 301 Moved Permanently to redirect the user to whatever full URL the URI is mapped to in map.txt. Note the "|http://mark.koli.ch" in the RewriteRule directive. This is important because if no URI matches in the RewriteMap map file, the "|URL" defines the default redirect location. In this case, if someone visits kolich.cc/bogusredirect I'll send them to my blog homepage, http://mark.koli.ch.
Enjoy.
FOLLOWUP
Why would you ever want to do this if bit.ly, tinyurl.com, and twurl.cc exist?
I wanted to learn more about RewriteMap. It surprises me that three of these services exist. They all do the same thing, and it took me less than five minutes to setup my own. Talk about a weak barrier to entry. It's interesting that these Web 2.0 startups are built on five minutes of real, actual, work.
How do you automatically add shortened URL's to your RewriteMap?
This would involve writing a small PHP web-app to generate a hash of your URL and then append it to your map.txt map file (something like this). I might use PHP's fopen("map.txt","a") to append another URI->URL mapping to my map file. Also, PHP's md5() function would be useful to generate a hash of the URL. A shortened version of this hash would become the URI. Perhaps I'll whip up an example in PHP and post it here when I have some free time. For now though, WYSIWYG.



Did you find this post helpful, or at least, interesting?