This is a Url Shortening Web Service similar to the likes of bit.ly, tinyurl.com or goo.gl albeit highly simplified
Features include
Clone this repo to your $GOPATH/src
on your local machine using
git clone https://github.com/gkeesh7/url-shortner.git
The project uses Go Modules now earlier it used to rely on glide
go build main.go
The application uses a Mysql based Persistent Data Store and connects to it once booting up.
It’s hence necessary that mysql is running on your machine and the corresponding Table schema is pre-existing in your Database.
Please follow the link in order install and configure MYSQL for your system
Execute the following SQL script in your Mysql shell in order to create the necessary schema
CREATE DATABASE url_shortner;
USE url_shortner;
DROP TABLE IF EXISTS `redirection`;
CREATE TABLE `redirection`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`url_id` varchar(20) NOT NULL UNIQUE,
`url` varchar(1024) NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`expiry` TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
DROP TABLE IF EXISTS `url_stats`;
CREATE TABLE `url_stats`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`url_id` varchar(20) NOT NULL,
`count` INT(11) NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
INSERT INTO `redirection` (`id`, `url_id`, `url`, `created_at`, `updated_at`, `expiry`) VALUES ('1', 'test', 'https://youtu.be/dQw4w9WgXcQ?t=43', '2020-01-08 14:05:37', '2020-01-08 14:05:37', '2030-01-19 14:05:37');
The above SQL script can also be found in the resources package for reference
resources/sql_scripts/url_shortner.sql
In case you need to configure DSN for your local MYSQL installation.
Please do remember to make changes into
config/database/gorm.go
The default DSN given is
"root:@tcp(localhost:3306)/url_shortner?parseTime=true"
The DSN pattern is
"username:password@tcp(localhost:3306)/database_name?parseTime=true"
Since the Service is written in Golang, Please make sure your GOPATH,GOROOT
variables are configured properly
Follow the link above to install and configure Golang for your system
Execute the following commands from the project directory to run the web service Backend on your system
go build main.go
./main ulimit -n 120000
To build the docker image and run the docker container.
#To build the image
docker build -t url-shortner .
#To run the image
docker run -d -p 8080:8080 --name url-shortner url-shortner
If you want to run the service along with monitoring using prometheus and grafana just execute
docker-compose up
Once the service starts running
try visiting http://0.0.0.0:8080/redirect/test
Thank me Later :)
NOTE:- If you are facing issues in configuration of ulimit for your MacOS please follow this guideline
The app can be deployed to kubernetes by running the following commands
##Create the Deployment
kubectl apply -f deployment.yaml
##Create the Service
kubectl apply -f service.yaml
##Port forward the 8080
kubectl port-forward deployment/url-shortner-deployment 8080:8080
The guide to make sure that the docker image gets built and pulled locally is here
For windows machines incase eval $(minikube docker-env)
might not work so save the image to a tar file and put into minikube
docker image save -o image.tar my_image:tag
minikube image load image.tar
For unit testing you can run the go test command and get the test coverage for the project
go test ./... -cover
As we can see that the logic and and utils are fairly well covered with unit Test Cases
For running a perf test you can execute the following go test command when the Service is running and it would execute a sample stress test on the running web service
go test resources/perftest/perf_test.go -v
As we can see that the backend took 0.5 seconds to shorten 1000 URLs
You can tinker around with the given perf test which doesn’t use any Performance testing framework, just plain Golang concurrency primitives
The following are rest APIs that the service provides
To redirect from the shortened url_id to actual long URL
curl -X GET \
http://localhost:8080/redirect/{url_id} \
-H 'cache-control: no-cache'
To shorten a URL
curl -X POST \
http://localhost:8080/shorten \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"url":"https://www.google.com/search?q=do+a+barrel+roll",
"request_id":"asdlfjhlaksdjffsajkflkjghjasfflkg"
}'
The JSON response format for the above Curl would be like
{
"request_id": "asdlfjhlaksdjffsajkflkjghjasfflkg",
"short_url": "http://0.0.0.0:8080/redirect/POnv0XFu9P",
"redirect_url": "https://www.google.com/search?q=do+a+barrel+roll",
"expiry": "2020-01-12T19:45:51.295175+05:30"
}
By Default all links expire 24 hours from creation time but, if you want a custom expiry time you can provide that as well with an additional expiry
field of Date type in the json
curl -X POST \
http://localhost:8080/shorten \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"url":"https://www.google.com/search?q=do+a+barrel+roll",
"request_id":"asdlfjhlaksdjffsajkflkjghjasfflkg",
"expiry": "2020-01-12T19:45:51.295175+05:30"
}'
To get URL opening stats (top 10 most frequently visited URLs in the last 24 hours in descending order)
curl -X GET \
http://localhost:8080/stats \
-H 'cache-control: no-cache'
The JSON response format for the above Curl would be like
{
"message": "The most frequent URL clicks/redirects in last 24 hours",
"url_stats": [
{
"url": "http://0.0.0.0:8080/redirect/POnv0XFu9P",
"count": 4
},
{
"url": "http://0.0.0.0:8080/redirect/vYyVeiUtUd",
"count": 3
},
{
"url": "http://0.0.0.0:8080/redirect/test",
"count": 1
}
]
}
Pull requests are welcome for a few features that are in the TODO pipeline