A Tiny URL design and code ✔️

This is a simple encode() and decode() function.

Note that we haven't created the MD5 hashing approach here as this only deals with the concept.

Step:

encode()

  • save the long url in db, get a unique long id from db for that url
  • pass that long id to the encode(id) function
  • so for a long value we keep diving it by 62 and pick a value from the allowed chars array and keep adding it
  • make sure to reverse the created string
private static final String allowedString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    private final char[] allowedCharacters = allowedString.toCharArray();
    private final int base = allowedCharacters.length; // 62

    public String encode(long input){
        var encodedString = new StringBuilder();

        if(input == 0) {
            return String.valueOf(allowedCharacters[0]);
        }

        while (input > 0) {
            encodedString.append(allowedCharacters[(int) (input % base)]);
            input = input / base;
        }

        return encodedString.reverse().toString();
    }

decode()

  • send the last part of the url - which is the encoded string
  • convert the string to array
  • from first value we pick index of value and multiply it with 62^remaining characters
  • the number is the decoded id
public long decode(String input) {
        var characters = input.toCharArray();
        var length = characters.length;

        var decoded = 0;

        //counter is used to avoid reversing input string
        var counter = 1;
        for (char character : characters) {
            decoded += allowedString.indexOf(character) * Math.pow(base, length - counter);
            counter++;
        }
        return decoded;
    }

So if we have the decoded url, we could simply return it as a header location - with the response code of 302 (FOUND)

@GetMapping(value = "{shortUrl}")
public ResponseEntity<Void> getAndRedirect(@PathVariable String shortUrl) {
        var url = urlService.getOriginalUrl(shortUrl);
        return ResponseEntity.status(HttpStatus.FOUND)
                .location(URI.create(url))
                .build();
    }
}

The problems:

  1. we are relaying on a single db table id to generate the ids
  2. not scalable, how do we handle a fixed size return url
  3. how do we allow customised URLs
  4. can we reuse a short-url which is removed/expired?

I will be working on a more distributed solutions in coming posts, Thanks you for reaching here.
Here's a 🍪

20