URL Shorteners:- A Practical Approach, Mini Project

URL Shorteners:- A Practical Approach, Mini Project

๐Ÿ”ฅ A Real world example of Tiny URL with beginner friendly implementation

ยท

4 min read

๐Ÿ“ Introduction

๐ŸŽฏ In today's world, we do share many things over the internet. And one of the methods of sharing is to share the URL of the content. We use Google drive to store, Youtube for Videos, Spotify for Music, etc. Whenever we want to share something from any platform the most common way is to share the URL.

๐Ÿ˜ฉ But sometimes, the URL gets too long or not making sense like Google Drive URLs (drive.google.com/drive/u/1/folders/1oue1LJP..)

๐Ÿ‘‰ So, here is where we can use URL shorter services like Bit.ly, TinyURL, etc.

DON'T GO TO HTTPS://TINYURL.COM/Y4P53E8A WORST MISTAKE OF MY LIFE - Storm  Troopers | Make a Meme

๐Ÿ“ 301, 302 Status Code

๐Ÿ™‚ Sometimes you can see that in the Network tab of our browser Inspect tools we do get 301 or 302 Moved Permanently as the Status code. This means that the URL is going to redirect us to the main URL.

๐Ÿ‘‰ Here, you can see when I opened Google Maps through the TinyURL link It gave me the code 301 which means it is going to redirect us to the main URL.

Note:- We'll see a basic implementation of the service, to let you guys know what are the basic requirements that a URL Shorteners should have.

  • Register a New Long URL

  • Register a New Long URL with Custom Short URL

  • Get a Long URL by providing a Short URL

  • Get the count of how many times a long URL visited

  • Deleting a long URL from the store

๐Ÿ™‚ To get a better idea, Follow this:-

๐Ÿคœ Note:- Here, we took a shortURL of syntax:- shortURL.com/xxxxxxxxx

Where, xxxxxxxxx is an AlphaNumeric String of length 9.

Below, you can find the implementation with a main file to test the code:-

  • URLShortnerInterface
package com.project.shorturl;

public interface URLShortnerInterface {

  String registerNewUrl(String longUrl);

  String registerNewUrl(String longUrl, String shortUrl);

  String getUrl(String shortUrl);

  Integer getHitCount(String longUrl);

  String delete(String longUrl);

}

Here, We have used an interface to follow some Design patterns.

  • URLShortnerImplementation:-
package com.project.shorturl;

import java.util.HashMap;

public class URLShortnerImplementation implements URLShortnerInterface {
    HashMap<String, String> map1; // longUrl->ShortUrl
    HashMap<String, String> map2; // ShortUrl->longUrl
    HashMap<String, Integer> map3; // longUrl->Integer

    URLShortnerImplementation(){
        map1 = new HashMap<>();
        map2 = new HashMap<>();
        map3 = new HashMap<>();
    }

    public String generateString(){
        String AlphaNumericString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"+ "0123456789";
        String result = "";
        for(int i = 0; i<9; i++){
            result += AlphaNumericString.charAt((int)(result.length()*Math.random()));
            // System.out.println("Generated String is : "+ result);
        }
        // System.out.println("-------");
        return result;
    }

    @Override
    public String registerNewUrl(String longUrl){
        if(map1.containsKey(longUrl)){
            return map1.get(longUrl);
        }
        String shortUrl = generateString(); 
        shortUrl = "http://short.url/"+shortUrl;
        map1.put(longUrl, shortUrl);
        map2.put(shortUrl, longUrl);
        return shortUrl;
    }
    public void printMap(){
        System.out.println("Map1");
        for(String key: map1.keySet()){
            System.out.println();
            System.out.print(key+" ");
            System.out.print(map1.get(key));
        }
        System.out.println("Map2");
        for(String key: map2.keySet()){
            System.out.println();
            System.out.print(key+" ");
            System.out.print(map2.get(key));
        }
        System.out.println();
        System.out.println("-----");
    }

    @Override
    public String getUrl(String shortUrl){
        if(map2.containsKey(shortUrl)){
            if(map3.containsKey(map2.get(shortUrl))){
                map3.put(map2.get(shortUrl), map3.get(map2.get(shortUrl))+1);
            }else{
                map3.put(map2.get(shortUrl), 1);
            }
            return map2.get(shortUrl);
        }

        return null;
    }

    @Override
    public String registerNewUrl(String longUrl, String shortUrl){
        if(map2.containsKey(shortUrl)){
            return null;
        }
        map1.put(longUrl, shortUrl);
        map2.put(shortUrl, longUrl);
        return shortUrl;
    }

    @Override
    public Integer getHitCount(String longUrl){
        if(map3.containsKey(longUrl)){
            return map3.get(longUrl);
        }
        return 0;
    }

    @Override
    public String delete(String longUrl){
        if(map1.containsKey(longUrl)){
            map2.remove(map1.get(longUrl));
            map1.remove(longUrl);
        }
        return null;
    }
}
  • The main method to test the functionalities:-
package com.project.shorturl;

public class URLShortnerMain {

  public static void main(String[] args) {

    URLShortnerImplementation UrlShort = new URLShortnerImplementation();

    String url = UrlShort.registerNewUrl("http://abc.com");
    String url1 = UrlShort.registerNewUrl("http://abc1.com");
    String url2 = UrlShort.registerNewUrl("http://abc2.com");
    String url3 = UrlShort.registerNewUrl("http://abc3.com");
    String url4 = UrlShort.registerNewUrl("http://abc2.com");  

    System.out.println(url);
    System.out.println(url1);
    System.out.println(url2);
    System.out.println(url3);
    System.out.println(url4);

    // Update new URL mapping to a custom short URL
    String url5 = UrlShort.registerNewUrl("http://abc5.com", "http://short.url/test1");
    String url6 = UrlShort.registerNewUrl("http://abc6.com", "http://short.url/test2");
    // Try to update new URL to map to existing short URL, should return null
    String urlNull = UrlShort.registerNewUrl("http://abc7.com", url3);
    assert(urlNull == null);

    System.out.println(url5);
    System.out.println(url6);
    System.out.println(urlNull);

    // Test out longURL lookup based on the shortURL input
    assert(UrlShort.getUrl(url).equals("http://abc.com"));
    assert(UrlShort.getUrl(url2).equals(xUrl.getUrl(url4)));
    assert(UrlShort.getUrl(url5).equals("http://abc5.com"));

    // Test out getHitCount() for a given long URL. 
    // Here the same long URL has been looked up 2 times as part of url2 & url4
    assert(UrlShort.getHitCount("http://abc2.com").equals(2));
    // Try to fetch hit count for a non existent long URL, should return 0 
    assert(UrlShort.getHitCount("http://abcn.com").equals(0));

    // From the short URL url1, remove the common section (http://short.url/) and remove any non alphanumeric character
    String choppedUrl = UrlShort.replace("http://short.url/", "").replaceAll("[^A-Za-z0-9]", "");
    System.out.println(choppedUrl);
    // The result should have only alphanumeric characters and be 9 characters long
    assert (choppedUrl.length() == 9);

    // Delete mapping for the long URL and confirm that the short URL lookup for that long URL returns null
    UrlShort.delete("http://abc6.com");
    assert(UrlShort.getUrl(url6) == null);
  }
}

๐Ÿซต There are some assertions embedded to test the code. This was the basic implementation or introduction.


๐Ÿคœ We can add Database support and notifications like if

  • Custom Short URL already taken

  • URL is deleted or not, etc


๐Ÿ’ป Our Next Blogs are going to be on DevOps, Scaling infrastructure, and Low-Level Design.

๐Ÿ”ฅ For more, Follow RealCS