Giter Club home page Giter Club logo

bitlygo's Introduction

Bitly Go

URL Shortener - Short URLs & Custom Free Link Powered by GoLang and PostgreSQL database.

Dependencies

  • Golang 1.18+
  • Tern 1.13+ (The SQL Fan's Migrator)

Getting started

  • Rename config.yaml.example to config.yaml, and tern.conf.example to tern.conf;
  • Change the database connection info with your own.

Run without docker

cd cmd/bitlygo/
go run main.go

Run as a docker container

NOTE: Make sure you changed the database connection info in docker-compose.yaml file

$ docker-compose build --no-cache
$ docker-compose up -d

Routes

GET /

This route will show this README to show the features of the projects to everyone.

POST /register

  • STRING username (required, The minimum length is 4 and maximum length is 88 also does not allow empty username)
  • STRING password (required)

This route will make new user if didn't exist

Example response:

{
   "username": "john",
   "api_key": "abcd-efgh-ijkl-mnop-124v-852a"
}

OR

{
   "status": false,
   "message": "Error message"
}

POST /login

  • STRING username (required)
  • STRING password (required)

This route will log into user account if exists

Example response:

{
   "status": true
}

OR

{
   "status": false,
   "message": "Error message"
}

GET /search

  • STRING q (required, The minimum length is 1 and does not allow empty queries also we will trim the value to make it ready to search) We will remove and skip all non-English and non-Digits characters and after that, if q is not empty we will search and fetch the results. Otherwise, throw an error!

  • POSITIVE INT limit (default is 10, Minimum value is 1 and Maximum is 100. Otherwise, throw an error!)

Example response:

{
   "status": true,
   "items": {
    "google": "https://google.com",
    "facebook": "https://fb.com/?from_my_site",
    "telegram": "https://t.me/"
   }
}

OR

{
   "status": false,
   "error": "Error message"
}

GET /top

  • POSITIVE INT limit (default is 10, Minimum value is 1 and Maximum is 100. Otherwise, throw an error!)

Example response:

{
   "status": true,
   "items": [
      {
         "name": "google",
         "link": "https://google.com",
         "visits": 300
      },
      {
         "name": "github",
         "link": "https://github.com/test",
         "visits": 255
      },
      {
         "name": "fb",
         "link": "https://fb.com",
         "visits": 200
      }
   ]
}

OR

{
   "status": false,
   "error": "Error message"
}

GET /expire-soon

  • POSITIVE INT limit (default is 10, Minimum value is 1 and Maximum is 100. Otherwise, throw an error!)

Example response:

{
   "status": true,
   "items": {
    "google": "https://google.com",
    "facebook": "https://fb.com/?from_my_site",
    "telegram": "https://t.me/"
   }
}

OR

{
   "status": false,
   "error": "Error message"
}

POST /add or POST /add/

  • STRING name (optional, If not defined, we will generate a short and unique random name)

  • STRING link (required, and we will check the link should be valid and pass URL standard format) About link value: we must support UTF-8 characters or query values.

If you send API-KEY in the headers, your short link will be alive for ever, otherwise, all links you are creating will only live for 2 days. It should be nice to easily config this limitation inside the source.

Note: you cannot create a duplicate name and It should throw an error. But it's okay to store the same link in different names.

POST /:name or POST /:name/

  • STRING link (required, and we will check the link should be valid and pass URL standard format) About link value: we must support UTF-8 characters or query values.

If you send API-KEY in the headers, your short link will be alive for ever, otherwise, all links you are creating will only live for 2 days. It should be nice to easily config this limitation inside the source.

Note: you cannot create a duplicate name and It should throw an error. But it's okay to store the same link in different names.

GET /:name

If the name is available on the databases. we will redirect the clients to the target URL. 301 redirect is fine.

Otherwise, we should alert that is a 404 (HTTP Status) route and display a 404 warning.

UPDATE /:name

  • STRING new_name (optional)

  • STRING link (required, and we will check the link should be valid and pass URL standard format) About link value: we must support UTF-8 characters or query values.

You can only update a link created by an API-KEY. So if the owner of that link is same as your API-KEY, you are allowed to update that.

Note: you cannot change the name, you only can change the link value and link that to another new URL.

DELETE /:name or DELETE /:name/

You can only delete links created by an API-KEY. So if the owner of that link is same as your API-KEY, you are allowed to delete.

Example response:

{
   "status": true
}

OR

{
   "status": false,
   "error": "Sorry, no permission"
}

Important NOTE: Note that search, add, expire-soon, and top are not allowed for names and we should make sure it's not allowed to create such names. since they are already reserved in the router.

The minimum allowed name length is 4 and the maximum is 25.

The name can only contain English and numeric characters. Any other character is ignored.

Database

It's okay to use PostgreSQL or MariaDB.

Note: since this project supports short lifetime links, we can use other databases too. but it's possible to use SQL and delete old rows.

Authors

  • Its Joniur
  • Max Base

bitlygo's People

Contributors

basemax avatar dependabot[bot] avatar itsjoniur avatar maxianedison avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

bitlygo's Issues

نظر / پیشنهادات / سوال در مورد پروژه

به نام خدا
سلام

جاهایی که از تابع GetUserByApiKey استفاده می شود احتمالا باید بررسی بشود که آیا کاربری یافت شده است یا خیر. مثل:

user := GetUserByApiKey(apiKey)
if user == nil {}

در چند جا این مورد کامل بررسی نشده است. مثل:

user := GetUserByApiKey(apiKey)
_, err = db.Exec(context.Background(), `insert into links(owner_id, name, link) values($1, $2, $3)`, user.Id, link.Name, link.Url)

Add docker

Hi, What's your opinion about add docker to the project and dockerize it?

Indexing name of links

Hi, what do you think about indexing the name of links, it can give us better performance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.