/url-shortener-service

URL-shortener service to shorten URLs. API clients will be able to create short URLs from a full length URL.

Primary LanguageTypeScript

URL Shortener Service

Star Count Licence Language

NodeJs Express

Table of content

  • [1] Application Description
  • [2] Application Functionalities
  • [3] Git Conventional Commits Message
  • [4] Flow Diagram
  • [5] File Structure
  • [6] How To Run
    • [6.1] local machine without docker
      • [6.1.1] configuration
      • [6.1.2] installation
      • [6.1.3] run
    • [6.2] local machine with docker ( Recommended )
      • [6.2.1] create docker network
      • [6.2.2] build images
      • [6.2.3] Create Containers
  • [7] How To Test
  • [8] OpenApi
  • [9] Acknowledgments

[1] Application Description

URL-shortener service to shorten URLs.
API clients will be able to create short URLs from a full length URL.
It will also support redirecting the short urls to the correct url.

[2] Application Functionalities

[2.1] Url Shortening
  • An API Client can send a url and be returned a shortened URL.
  • An API Client can specify an expiration time for URLs when creating shortened URL
  • Handle visits to Shortened URLs, they must redirect to the original URL with a HTTP 302 redirect, 404 if not found.
  • Visiting expired URLs must return HTTP 410
  • Input URL should be validated and respond with error if not a valid URL
  • Regex based blacklist for URLs, urls that match the blacklist respond with an error
  • Hit counter for shortened URLs (increment with every hit)
[2.2] Admin API
  • Admin api (requiring token) to list
    • Short Code
    • Full Url
    • Expiry (if any)
    • Number of hits
  • Above list can filter by Short Code and keyword on origin url.
  • Admin api to delete a URL (after deletion shortened URLs must return HTTP 410 on visit)

[3] Git Conventional Commits Message

[Type] : Message
Type =>  [Create], [Modify], [Fix], [Delete]
Message =>  Describe about the commit

Example
[Create] message event for bla bla bla
[Modify] message event for bla bla bla
[Fix] message event for bla bla bla

[4] Flow Diagram

[4.1] Chache Layer Flow

[4.2] Admin API Flow


[5] File Structure

-api
├── __tests__                         # for testing
│   └── integration                   # for all the integration tests 
├── src                               # for typescripts
│   ├── app                           # AS AS Open/Close Principle
│   │   ├── controllers
│   │   │    └─ ...
│   │   │       ├─ controller.ts
│   │   │       └─ events             
│   │   ├── middlewares               
│   │   ├── models                    # for database table
│   │   └── routes                    # for admin / user / swigger api routes
│   ├── core                          # AS Single Responsibility Principle
│   │   ├── common
│   │   │    ├── cache                # redis
│   │   │    ├── database             # mysql
│   │   │    └── validator  
│   │   │         └── rules           # we can add additional rules
│   │   │             └── ...
│   │   ├── functions                 # For Resuable functions
│   │   ├── http                      # For Express
│   │   ├── types
├...
├docker
├── config                            #
│   └── ...
├...
├── resources                         # images for readme file
│   └── ...

[6] How To Run

We have to choose our environment that where we will host our application.
In this moment, I will make cover for two environment.

[6.1] local machine without docker

first we need already installed node , mysql into machine.
for second, we have to configure.

[6.1.1] configuration

create .env file ./api/.env with the following content

(you have to replace with yours.)

REST_SERVER_HOST=localhost
REST_SERVER_PORT=9090

DB_SERVER_HOST=localhost
DB_SERVER_PORT=3306
DB_SERVER_USR=username
DB_SERVER_PASSWD=password
DB_SERVER_DB_NAME=databasename

REDIS_SERVER_HOST=redis-host
REDIS_SERVER_PORT=redis-port
[6.1.2] installation
cd api
npm install
[6.1.3] run
cd api
npm run dev
then we can access to http://localhost:9090 , you may need to check the port
[6.2] local machine with docker ( Recommended )
[6.2.1] create docker network
docker network create \
  --driver=bridge \
  --subnet=172.3.0.0/16 \
  --ip-range=172.3.0.0/24 \
  urlshortenernetwork
[6.2.2] build images
database image
docker build -t urlshortener:databaselayer \
  --build-arg db_host=localhost \
  --build-arg db_port=3306 \
  --build-arg  db_user=root \
  --build-arg db_password=password \
  --build-arg db_name=urlshortenerservice \
  --no-cache -f ./docker/databaseDockerfile .
application image
docker build -t urlshortener:application \
  --no-cache -f ./docker/applicationDockerfile .
[6.2.3] Create Containers
cache container
docker run --name cachecontainer \
--network=urlshortenernetwork \
--ip 172.3.0.15 \
-d redis
database container
docker run -i -t -d --name databasecontainer \
  --network=urlshortenernetwork \
  --ip 172.3.0.10 \
  --privileged urlshortener:databaselayer
application container
docker run -i -t -d --name applicationcontainer \
  -p 9090:9090 \
  --network=urlshortenernetwork \
  --ip 172.3.0.12 \
  --privileged urlshortener:application

clean all images of urlshortener

docker rmi $(docker images urlshortener -q) -f

For future, I will make cover for

  • ECR/ECS
  • Lambda(Function/Layer/APIGateway)

[7] How to Test

This test support only for "local machine without docker"

Unit Test

command

cd api
npm run test:unit

Screen Shoot for "Unit Testing"

Integration Test

command

cd api
npm run test:e2e

Screen Shoot for "Integration Testing"

Test all in once

command

cd api
npm run test

Screen Shoot for "All In One Testing"


[8] OpenApi

Pls let me assume our api is http://localhost:9090 .
So, our swagger url will be http://localhost:9090/swagger/
Screen Shoot :

[9] Acknowledgments

Hello Visitor, I just want to let you know what a pleasure it was.

I am truly grateful for the opportunity to speak with you and I look forward to hearing from you soon.