I guess you could say sometimes I care a bit too much about stupid things… this is one of those things. I really really like short and straightforward URLs. What follows is a description of a script that takes care of exactly that, making it super easy to manage those urls using github.
What I’ve been doing so far is having a redis database with all my urls and a simple python script with Flask that does this
While that actually worked, it was a PITA to actually update a link… I’d have to ssh into the server, open redis-cli
and update it. Also, I’ve recently added cloudflare everywhere to have them cache my sites, that means I now need to purge the cache once URLs are updated (I’m having cloudflare cache my content for 30 days, and whenever I update the content, I purge it).
In my ideal scenario, I would handle a file containing all the url mappings, and that should be it. Modifying the file should modify the redirections… and, the most natural way to handle those files for me is obviously git. Github has webhooks, what means I can get a notification every time the urls file is modified for free (literally).
Also, cloudflare’s API has a very convenient method to purge the cache… so this was just about fitting all the pieces together.
Basically, this script has two endpoints… /refresh
that… well, refreshes the URLs and /whatever-url-you-set-up
that does the redirection. Then, I set up a github webhook to hit /refresh
whenever I do a push and that in turn fetches the urls files, reloads them on redis and purges the cache on cloudflare. BUT… github has a small delay between the moment you push and when they make the content available on their website, so I added a &wait
parameter that just waits as many seconds as requested before actually pulling the urls.
I hope the idea is clear by now, and you can see the code on github (it’s just one tiny file doing everything). The script uses the following environemnt values:
-
CONFIG_FILE
: path to a configuration file containing the refresh key and the list of domains with their urls file paths -
REDIS_HOST
: the hostname of the redis server it uses -
REDIS_DB
: the database you want it to use
The configuration file is a simple json file, this is mine
The schema is pretty self-explanatory, but here’s a detail:
-
key
: this is the key you’ll have to pass torefresh
to have the system actually refresh the urls -
domains
: an object containing the domains you want the script to handle.-
urls
: contains a url to the file containing the redirections -
afterRefresh
: an optional parameter, if it’s present, this script will be executed… well, after refreshing the domain :)
-
And the urls
files are also pretty straightforward… just an object containing slug: destinationUrl
either as a json file or as a yaml file (you can see my file here)
Once that’s taken care of, all you need to do is set up a webhook on your redirections repository on github to https://yourdomain.com/refresh?key=thisIsACrazySecretNobodyKnows&wait=10&domain=domaintorefresh.com
and that’s it! and if you are using cloudflare, just call their API on your afterRefresh
script.
That works, and you can use it just like that by running gunicorn… but I really like docker. I have everything dockerized on my server and this is not the exception, so I made a docker container with everything it needs to run (python + my script + dependencies + redis), so that I don’t have to manage anything.
If you want to go that route, you should totally use it via docker compose, here’s my docker-compose.yml
. I have a web
custom network that’s what the dockerized nginx server uses to reach the different containers, so that I don’t have to bind the ports to the host… but if you don’t want to go that route, you can just map the port 8000
Then, you can put an nginx as a reverse proxy… here’s my site config
aaaand… that’s it! super straightforward, right? I’m setting Cache-Control: s-maxage=1
for the /refresh
endpoint so that cloudflare doesn’t cache that ;)