Issue 77 * August 20 2009

The Shortest Route
Creating a URL shortening service with RevServer

by Andre Garzia

Have you ever had trouble with web addresses that seems like they go on forever with thousands of fields and parameters? Have you ever tried pasting a Google Maps URL to a friend? Have you ever been caught trying to get a short URL to put on twitter? Well, welcome to the club. There are some wonderful web applications out there but the urls they use are impossible to remember. That's why recently, many URL shortening services have appeared. These services basically pick a long URL and create a short one that is more manageable. When you go to the short URL it redirects to the long one, it is as if you had typed those infinite long URLs all by yourself. Now, how much work would it be to create a simple URL shortening service in Revolution?

The answer is 38.

I don’t mean 38 like Douglas Adams meant 42. I mean 38 lines of code including the HTML interface and during this brief article, we will build it together. First let us deconstruct our problem. There are two cases when our system is used. Case number one, a user has a long URL and wants to use our system to create a short one. Case number two, the user is trying to access one of our short URLs and we should redirect him to the long one. Let’s begin by investigating the first case.

Creating the HTML interface

This is a service that matches long URLs to short ones. It will generate short URLs like

http://myServer/EDQN4J

where EDQN4J is a code that represents the long URL. First question is how will we store those relationships? One might consider using XML or MySQL to do this job but since we’re creating a really simple service, let us do it with dumb plain text files. In our system each of those codes (eg: EDQN4J) will be a text file on the server. The content of this text file will be the long URL, so a file like EDQN4J might contain http://andregarzia.on-rev.com/cms.irev (which is not a long URL by the way but serves as an example). To make things more tidy, we’ll store all those text files inside a folder named “urls”, below, is a shot from my setup with some files in it already.

url folder

Now let us create the form and code to save those text files. The form is a simple one, we just need one field, the long URL, and one button that submits the form. No other data is needed to perform our service duties. So the form looks like:

<form method="post" action="index.irev">
<p>URL:<input type="text" name="url" size="150"/></p>
<p><input type="submit" value="Do it"/></p>
</form>

Very simple and straight forward, right? Let us look at the code that saves the data submited by this form. Keep in mind that this form is using the post method, so all fields sent by this form to the server will appear in the $_POST array. We can simply check for the presence of $_POST[“url”], if this field is not empty then we generate the code for the small URL and save the text file.

The important question is, how do we generate safe short codes? We need something that does not repeat, so that every request can be safe. Our time here on earth never repeats, I measure my time here in milliseconds, so why don’t we use the milliseconds of the computer for our code. Unless the computer travels in time, that value should not repeat. You might think that a value like 1250705087635 is too long, and you'd be right, that is 13 characters long, an absurd waste of space. There’s a clever way to make that big number appear shorter though, we can switch bases. Instead of base 10 why don’t we up the integers by using base 36, this way a value such as 1250705087635 becomes EDQN4J. If you don't believe me, you can check it with a simple call to your message box with: put baseconvert("1250705087635", 10, 36). Now, we can generate a unique code that is just six letters long which will do the trick. The code for saving a long URL as a short one is:

if $_POST["url"] is not empty then
put baseconvert(the millisecs, 10, 36) into tCode
put $_POST["url"] into URL ("binfile:urls/" & tCode)
end if

The code is dead simple, we pick the value passed from the form, generate a code for it and save it as a text file. So that deals with the user case one we specified above: a user comes to our service and has a long URL and wants a short one. That is done. Let us look how to pick the short one now and redirect back to the long.

There and Back Again

Let us review what we need now. The user has a code like EDQN4J and wants to be redirected to the long URL it represents. One might want to code another form, so the user enters the code and he is redirected, but this adds an extra step to the task of being redirected and spoils the purpose which is having short URLs that work just like the long ones. So let us just pass the code in the URL itself as a parameter like:

http://myServer/index.irev?code=EDQN4J

By trying to access this URL the user should simply and transparently be redirected.

To redirect a user we can use a HTTP 301 redirect response. To do that we need to pass apache (thats your webserver name) two HTTP headers. One is the status code, which is 301 temporary redirect and the other is a location saying where the browser should go. So when the user goes to http://myServer/index.irev?code=EDQN4J the server answers that the page has moved to a new address and tells the new location. This is transparent to the user and the code picking the URL from the code and redirecting it is fairly easy:

if $_GET["code"] is not empty then
get URL ("binfile:urls/" & $_GET["code"])
put new header "Status: 301"
put new header "Location:" && it
put "redirecting"
exit to top
end if

What is happening here? First we check if a code was passed in the URL, if so, we pick the value from its file and use the put header command to redirect the user, we also exit to top to prevent the rest of the HTML interface from appearing. Right, we’ve just created a fancy web 2.0 like URL shortening service. Let us put the full code in here:

<?rev
if $_GET["code"] is not empty then
get URL ("binfile:urls/" & $_GET["code"])
put new header "Status: 301"
put new header "Location:" && it
put "redirecting"
exit to top
end if

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Haggis URL - URL Shortening Service</title>
</head>
<body>
<h1>Haggis URL</h1>
<h2>URL Shortening service</h2>
<?rev
if $_POST["url"] is not empty then
put baseconvert(the millisecs, 10, 36) into tCode
put $_POST["url"] into URL ("binfile:urls/" & tCode)
?>
<p>Your short URL is:<a href="?code=<?rev put tCode ?>">http://<?rev put $_SERVER["HTTP_HOST"] & $_SERVER["REQUEST_URI"] & "?code=" & tCode ?></a></p>
<?rev
else
?>
<form method="post" action="index.irev">
<p>URL:<input type="text" name="url" size="150"/></p>
<p><input type="submit" value="Do it"/></p>
</form>
<?rev
end if
?>

</body>
</html>

And that's all folks, a simple thing to implement but it is really useful. In how many languages could you implement a full useful web application in 38 lines? Not many I believe. This system is online at:

http://andregarzia.on-rev.com/haggisurl/index.irev

in case anyone wants to give it a try. For example, try to access

http://andregarzia.on-rev.com/haggisurl/index.irev?code=ECJ3VL

This will redirect you to a enormously long Google Maps address pointing to the Dynamic Earth where in couple weeks we will have our RunRevLive conference. See you all there!

About the Author

Andre Alves Garzia is 28 and lives in Brazil. He is usually coding something network related and created RevOnRockets. When not working, he enjoys SF Books, sailing and making pizza.

Main Menu

What's New

Revolution Conference