Post

How to build a Shortened URL By Ruby On Rails like Bitly or Twitter

How to build a Shortened URL By Ruby On Rails like Bitly or Twitter

Give a website shortenedUrl to convert longURL to short URL with alpha lexigraphy encoded/decoded response to User.

  • Give two endpoint
    • encoded
    • decoded
  • Extra default enpoint is index, and retore lasted encoded url
  • About algorithm used on website. I use Bijective algorithm to make a alpha lexigraphy short url.
  • Give rate limit process to request IP and prevent attack vector. I was use gem rack-attack for this case to handle limit request per IP is 5 request to 2 second. other wise, better to authentic user before they use api. To do this prevent, can implement a mechanism authentic by a system by api key for user indetify and in session.
  • System was give an URL with a unique shortURL to decrease weight in database and open scale up if have mutilple dabase installed.
  • To prepare for scale up:
    1. Give a better cache system support Rate limit.
    2. With URL was created before, we change to operation select instead create same URL.
    3. Given a load ballancing to suppot this load is even better than server serve every single request.
    4. Architecture from Monolith or micro service and under control of load balancing give us a good reputation.

Install System

  • Ruby version ^2.5~3.0
  • Rails
  • rack-attack gem
  • Rspec
  • factory_bot_rails
  • faker

To install run command below:

1
bundle

API in use

Three enpoint with two default enpoint(/api/v1/shortner/):

  • index /api/v1/shortner: Get method
    json response:
    1
    2
    3
    4
    5
    
    {
      "message": "Hello shortner",
      "encoded": "q",
      "url": "http://google.com"
    }
    
  • encoded /api/v1/shortner/encoded: Post method
    Json request:
    1
    2
    3
    
    {
      "url": "http://google.com"
    }
    

    Json Response

    1
    2
    3
    4
    
    {
      "url": "http://google.com",
      "decoded": "b"
    }
    
  • decoded request /api/v1/shortner/decoded: Post method
    Json Request
    1
    2
    3
    
    {
      "encoded": "e"
    }
    

    Json Response

    1
    2
    3
    4
    
    {
      "url": "http://google.com",
      "status": 200
    }
    

Last URL saved

  • Last user saved was restore in Database. I was use default by sqlite3. But for better performance and production case need to setup dabase with MYSQL or PostgresSQL.

encoded

1
2
3
4
  def generate_slug
    last_id = ShortenUrl.last ? ShortenUrl.last.id : 1
    self.slug = Bijective.bijective_encode(last_id)
  end

decoded

1
2
url = ShortenUrl.find_by_slug params[:encoded]
url.url

Algorithm to conver longURL to Short

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Bijective
  ALPHABET =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".split(//)
    # make your own alphabet using:
    # (('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a).shuffle.join

  def self.bijective_encode(i)
    # from http://refactormycode.com/codes/125-base-62-encoding
    # with only minor modification
    return ALPHABET[0] if i == 0
    s = ''
    base = ALPHABET.length
    while i > 0
      s << ALPHABET[i.modulo(base)]
      i /= base
    end
    s.reverse
  end

  def self.bijective_decode(s)
    # based on base2dec() in Tcl translation 
    # at http://rosettacode.org/wiki/Non-decimal_radices/Convert#Ruby
    i = 0
    base = ALPHABET.length
    s.each_char { |c| i = i * base + ALPHABET.index(c) }
    i
  end
end

Test application with Spec

Test case was specified with controller and function endoint. To run test from root of project run command:

1
rspec

Sumarize

Give a website for serve enpoint to convert long url to short url, you can find source code at my github repository.

This post is licensed under CC BY 4.0 by the author.