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

Posted by Hardwork đẹp trai on April 16, 2022 · 6 mins read

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.