Skip to content

URL Shortening

Two days ago, I had something that I really wanted to share with my friends, so I uploaded it to my personal file sharing server. But the sharing URL was long, about 60 characters. I thought, if I could provide a shorter and easier-to-remember sharing URL, probably more people will visit the shared file. But none of the existed URL shortening services satisfied my need. I end up making my own URL shortening system.

Before I started reimplementing the wheel, I tried several URL shortening services.

TinyURL can shorten the URL from 62 chars to 28 chars. goes to 21 chars. also goes to 21 chars.

All of them do pretty well on shortening the URL. So let me compare some other features.

Neither of the first two services provides visit counters. does provide a good many of useful analytical data, including visit counter, referrer, visitor country, visitor browser, visiter platform, etc.

Apparently, Google wins.

TinyURL provides customizable short URL. and, on the other hand, do not provide such feature.

TinyURL wins.

Hmm. What if I want both TinyURL’s customizable URL and’s analytical data?

My first thought was to ‘chain’ these two URL shortening services, that is, a user visits an easy-to-remember TinyURL shortened URL, and gets redirected to an analytical-data-rich shortened URL, and then finally gets redirected to the original URL.

But wouldn’t that be too complicated? It is also wasting the network resource by routing to unnecessary extra servers. I do not want my clients to wait for a long time before they get redirected to the final URL.

Another very important factor is that many of my friends are located in China, which means they have restricted access to Google services. Although Google is trying hard to make a come back to mainland China, the Chinese government is still blocking most of Google’s services. Thus, I do not expect to work well in China.

Finally, I decided to make one myself. There are several benefits of doing this on my own domain.

  • All short URLs are available for me. There will be no collision on hot URLs, simply because I am the only person using this short URL system on my domain.
  • Highly customizable that no online services could provide. Namely:
    • Set the short URL to automatically expire after a period of time;
    • Set the short URL to automatically expire after a certain number of visits;
    • Packets Time-To-Live;
  • Extra useful features:
    • Get data about referrer;
    • Get the client IP;
    • Email/text notice when the URL is visited.

These features are actually very handy. I can keep track of who visited my link, knowing who is my “fan”. I will know what kind of contents my friends like. etc.

The most important one is customizable, collision-free short URLs. I can use URLs as short as 1 character, without getting frustrated by the URL taken by someone else.

The idea of the URL shortening system is very simple. It is basically a pair structure: a short URL corresponds to a long URL. When the server gets a request to a short URL, the server inserts a history (with remote_ip, user-agent, referrer, and some other interested information) into the database, then it looks up for the long URL and redirects the client to the long URL.

To shorten the URL as much as possible, I want to hide the /index.php?url=[REQUESTED_URL] thing. Thus, a URL rewrite is needed. Basically rewrites every [REQUESTED_URL] to /index.php?url=[REQUESTED_URL]


gets rewrite to

and then gets redirected to

See how short it is? And have a look at the log.

Short URL    thx
   Long URL
  Remote IP
       Time    2018-02-04 16:43:45 UTC-8
 User Agent    Mozilla/5.0 (X11; Linux x86_64) Chrome/63.0.3239.132
Request URL    /thx?app=wechat&from=timeline

Basically, everything I wanted is included in the log.

This project is deployed on

The code is ugly and highly unstructured (with a lot of use of goto label). But anyway, it works.

The source code is available on GitHub

MIT License.

Published inCoding Stuff

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *