featherbear.cc/go

Posted

 GitHub: featherbear/go-links


Sometimes I have links or websites that I want to share to people, as well as one or more of the following conditions

There are heaps of URL shortening services, some of which also include free services for using your own custom domain names, however I didn’t want to set up a subdomain, or purchase a new domain for this purpose. I wanted these links to be part of my main domain featherbear.cc


The first step would be to consider how I wanted to host this service…

Use Case: A user will navigate to a link, which will then redirect them to another page.

To do this, we could have a web-server send a 301 or 302 HTTP redirect code, such as one running Python-Flask / Node-Express / etc… However, there is a much simpler way!

A webpage can use a meta redirect tag to navigate to a new page. We could use JavaScript to change the location.href or similar. (Note: In terms of SEO, this is a bad idea - But I don’t care about SEO for my short links)

If I use a meta redirect or JavaScript, I won’t need a scripted backend server - rather all I need is just a static site (that serves index.html by default). For example, GitHub Pages (where most of my static sites are hosted!!!).

To create the files for each shortened link, I will need some sort of script to run - which is where GitHub Workflows comes in!

The Redirect Page

The redirect page will be the index.html file that the user visits, that will contain the logic to redirect the user to the correct destination.

As bare minimum we just need meta http-equiv="refresh" content="0;url=http://somewebsitehere.com" />

The 0 means that the page will redirect to http://somewebsitehere.com instantly.
If I wanted to have a 5 second delay, I could change content to "5;url=...

In JavaScript we could emulate this 5 second delay with

setTimeout(() => {
  location.href = "http://somewebsitehere.com"
}, 5000)

I went ahead and prettified my redirect page so it looks something like the following

The 404 Page

GitHub Pages supports a fallback webpage 404.html that will be displayed if the requested page could not be found.

I tweaked my redirect page so that it looks like this

The Generator Script (Python)

After the client-side pages were done, I wrote a script in Python to handle the redirect file creation. It reads a redirect file template, and replaces the redirect URL for each code in a JSON file.

#!/usr/bin/python3

import json
from encClient import generate

from pathlib import Path

with open("template.html") as f:
    template = f.read()
with open("template_password.html") as f:
    template_password = f.read()

def writeFile(CODE, data):
    Path(f"public/{CODE}").mkdir(parents=True, exist_ok=True)
    with open(f"public/{CODE}/index.html", "w") as g:
        g.write(data)

with open("links.json", "r") as f:
    data = json.load(f)
    for CODE in data:
        entry = data[CODE]
        if type(entry) is dict:
            if "expiry" in entry:
                continue
            if "password" in entry:
                writeFile(CODE, template_password.replace(
                    "$ENC_STRING", generate(entry["link"], entry["password"]).decode('utf-8'), 1))
                continue

            writeFile(CODE, template.replace("$REDIRECT_URL", entry["link"]))
            continue

        writeFile(CODE, template.replace("$REDIRECT_URL", entry))

It’s fairly straightforwards

GitHub Workflows

After the script was written, we need the script to run by itself every time I update the JSON file.

In my repository I created a YML file at .github/workflows/build.yml (the name of the file itself doesn’t really matter, just ensure it’s in the .github/workflows directory)

This YAML file installs any required Python packages, runs my generator script, then publishes the output to GitHub pages

You can learn more about GitHub Workflows here

name: build short links

on:
  push:
    branches:
    - master

jobs:
  build-deploy:
    runs-on: ubuntu-18.04
    steps:
    - uses: actions/checkout@master

    - name: Install python packages
      run: python3 -m pip install -r requirements.txt

    - name: Generate short links
      run: python3 generate.py

    - name: Deploy
      uses: peaceiris/actions-gh-pages@v2.3.1
      env:
        PERSONAL_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        PUBLISH_BRANCH: gh-pages
        PUBLISH_DIR: public

At this stage, everything should be working; and after enabling GitHub Pages on my repository and waiting for a minute or two, my static pages were up and visible!

For example

Tracking / Analytics

To add page tracking I just whacked on a Google Tag script, which you can easily grab from the Google Analytics portal.

Password Protection

In an attempt to stop deter people from visiting random links (i.e IDOR and/or bruteforce), I decided to add some password protection.

Note: Obviously, this won’t stop someone who has the password from sharing the redirect URL directly to someone else. But it will stop bots and crawlers from screwing up my analytics and stuff!

During redirect file generation, for links requiring a password the Python generation script will encrypt the redirect link with an AES-CBC cipher, whose AES key is derived from a PBKDF2 function of the passphrase.

The client browser’s WebCrypto API will then decrypt the link, provided the correct password!


This was a fun and quick little project to do to get back into coding, as I haven’t done much since the start of 2021. I’ve been busy with my summer university courses (DART1130 - Photography and PSYC1022 - Psychology of Addiction), but now that they’re wrapping up I’ll hopefully have more time to commit to my work projects and side projects like these!

More posts

Review: Canon EOS R

Comments on the EOS R

Posted

UNSW PSYC1022

Psychology of Addiction

Posted