Puny Shortener - Get Short URL's Hombre!

  • By Doutor Finanças
  • Last update: May 3, 2023
  • Comments: 6


Latest Release CircleCI codecov Github Actions APACHE-2.0 License CodeFactor

PUNy-SHOrtener - Yet Another URL Shortener


Spelled pan‧cho - ˈpãnʲ.t͡ʃo

But, Why?


props to XKCD

We decided that we need something that doesn't exist on every other project (mix all of them , and you would have it).

So, we decided to make yet another URL shortener.


you can clone this repo or use one of the precompiled binaries available in the release section

you can also use docker, pre-made images are available for you at docker pull ghcr.io/doutorfinancas/pun-sho:latest or you can

# this API_PORT is defined in .env file or put it in env itself
export API_PORT=8080
docker run --env-file=.env -p 8080:${API_PORT} -t ghcr.io/doutorfinancas/pun-sho:latest pun-sho 

you should also copy the .env.example to .env and fill the values for the database. you can use either cockroach or postgres as value for the DB_ADAPTOR

if you use cockroach, you can create a free account here

DB migrations

This project uses database migrations. For any changes on the DB structure to be dealt with or replicated or rolled-back we use a migration tool

Install golang-migrate

# cockroach
go install -tags 'cockroachdb' github.com/golang-migrate/migrate/v4/cmd/[email protected]
# postgres
go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/[email protected]

Create new migration files

make migration/create


To go versions up:

make migration/up

To go versions down:

make migration/clean

Create a short link

read -r -d '' BODY <<EOF
  "link": "https://www.google.pt/",
  "TTL": "2023-03-25T23:59:59Z",
  "qr_code": {
    "create": true,
    "width" : 50,
    "height": 50,
    "foreground_color": "#000000",
    "background_color": "#ffffff",
    "shape": "circle"

# you could use "background_color": "transparent" to request a png without background
# by setting env property QR_PNG_LOGO to a png filepath, 
# it will overlay the logo on qrcode center

curl -XPOST https://yourdomain.something/api/v1/short \
  -H 'token: Whatever_Token_you_put_in_your_env' \
  -H 'Content-Type: application/json' \
  -d $BODY 

this would render an answer like:


Get statistics from a visited link

curl -H 'token: ThisIsA5uper$ecureAPIToken' https://yourdomain.something/api/v1/short/c62cbe57-7e45-4e87-a7c1-11cfb006870b 

this would render an answer like:

  "accesses": [
      "meta": {
        "meta_collection": [
            "values":["gzip, deflate, br"]
      "user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/ Safari/537.36",
      "extra":"Map: map[]",
      "os":"macOS 10.15.7",

Get a list of links

curl -H 'token: ThisIsA5uper$ecureAPIToken' https://yourdomain.something/api/v1/short/?limit=20&offset=0

will return a list of short links, using pagination

Deleting a link to make it inaccessible

curl -H 'token: ThisIsA5uper$ecureAPIToken' -XDELETE https://yourdomain.something/api/v1/short/c62cbe57-7e45-4e87-a7c1-11cfb006870b


We are currently working actively in the project and as such there still isn't a closed API.

we will be releasing 0.X until we bind a contract to the API

Next Steps

  • Define stable contract version
  • Add GUI (web based) with:
    • Base login page
    • Dashboard with overview
    • Ability to track a specific link data
    • Show list of links with filters (by date range, status)
  • Allow better security (oauth2 or even simple jwt)
  • Add GitHub pages with openapi/swagger definition




  • 1

    Cache-Control max-age should be set on successful redirection

    Currently we redirect users with 301. This means that a user only passes our service once, and cache will then keep the user out, so no statistics for the service.

    We should add Cache-Control with a max-age policy of 90, following industry practices, to prevent this and allow stats gathering

  • 2

    Create ability to return a QR code when a short link is created

    we need to have a shortlink QR code created

    • Must return base64 image
    • Must have flag to request it
    • Must have config setting to set an icon
    • Must have config setting to set a color
  • 3

    Create DELETE endpoint for pun-sho

    Currently pun-sho does not allow for deletion (soft) yet. This feature request is simply to have a DELETE /api/v1/short/:UUID: method that places the deleted_at as now.

    If deleted_at is set, then redirects should no longer happen. We should still be able to collect statistics on this and track them

  • 4

    feat: #1 Restrict the access to a shorty URL by the number of redirects

    • Create migration to add column "redirection_limit" in the "shorties" table
    • Add a condition regarding the "redirection_limit" in the "CreateVisit" function, that will verify if the limit was reached
    • Export two parts of the code in the "FindShortyByID" function to two other functions ("FindAllAccessesByShortyID" and "CountRedirects")
    • Add a new status ("StatusLimitReached"), to be used when the number of redirections limit was reached
    • Create Intellij http-requests with some tests
    • Edit Makefile so we can have 3 commands to run tests. One which runs everything, one that runs Go tests and another one that runs http-requests (which contain a few tests).
    • Add a "Tests" section in the documentation
    • Edit some of the documentation to make it more consistent and easier for other people to understand and follow it
  • 5

    Create filters for list short URL

    It would be nice to have the ability to filter URLs from list and to have a grouping mechanism, such as key or group that would allow one to have a contextful list returned

    • Create group or key filter to act upon a new field, which is optional (must)
    • Create start_date and end_date filter to act upon created_at (should)
    • Create status filter to act upon the state of the short, checking by deleted_at or if a redirect happen (could)
  • 6

    Create ability to redirect by a number of times

    I would like to have redirection limited not only by TTL, but also by number of redirects. There are cases in which I want a link to expire after a single time, other , after 5 times or an arbitrary number.

    Not passing the value or passing 0 should be treated as infinite.