Goblog: GIN powered JSON and HTML rest endpoints with a testing framework

#blog #gin #github #go #golang #gorm #html #json #oauth #rest #simpleMDE #sqlite

 

A few weeks ago, I set out to learn a bit of go, and rewrite my blog software. Previously I had been using a wordpress install with a DIY template, and some custom plugins. This worked pretty great for quite a long time, but I wanted to learn something new.

I played around with some javascript frameworks, and also experimented a bit with Jekyll to generate static pages from markdown for github pages hosted content. This was pretty good but I really wanted to play around with endpoints as well.

When I first started this project, I knew I wanted a JSON api which I could use to create, edit and delete posts. I also wanted to be able to query for posts. Eventually I wanted to have an extension to the api to support comments. In order to keep everyone from being able to post, I need authentication and authorization. I also eventually wanted to be able to add files to posts, again using the JSON api.

The idea with this would be that I could then use whatever I liked for the front-end / templating. Originally I started with a single page app approach using a javascript framework for the front-end, but eventually when I discovered how the go html templating worked, I decided to abandon that and keep everything server-side.

The gin framework is used for routing. It's been mostly really quick and easy to learn - with a few annoyances (for instance if I want to have a path with posts/:yyyy/:mm/:dd/:slug, I can't also have a path with just posts or there will be a conflict. I think there are some ways around it, but its not quite as clean as I was expecting.

I have two sets of routes, one for the JSON api and one for the HTML api, which renders the templated UI.

For authentication, I use the github oAuth to get an access token. I also retrieve the github profile, and use the username provided back from github to decide whether to provide admin access or not.

To store posts, to be quick and dirty, for now I'm just using sqlite. To provide a mapping between go structs and the database schema, I'm using gorm. Right now, there are users, posts, and tags - but eventually I'll support comments or something. I was also considering files to keep track of uploaded files / metadata, but for now - I just dump them into an uploads directory.

For deployment, I have set the go server to run in a docker container. When I cut a new release of the software, I build a new docker image which is a go build of the server, and then push it to docker hub. On my server, I have dev and www subdomains which point to different docker images - one where I can test first, and then once I'm confident roll out to www. I've got all this setup using saltstack. Both are actually hosted on the same machine behind an nginx proxy (I didn't bother hosting via aws or gcp because I wanted to be as cheap as possible and am just hosting on a spare machine at home).

So far its been fun to learn a bit about go, and the site seems to be decent at staying online. Right now, I've got a setup to run tests when I push using Github actions (although admittedly the coverage is pretty low). I'll be working to increase coverage now that the code is becoming more mature shortly. I'm sure there are many security vulnerabilities which I have not thought about yet, so I wouldn't use this for production anything. I've also got a TODO list in the readme with features I'm still adding. In the meantime, this should work well enough to start blogging again. Feel free to try out the code yourself, submit PRs, etc. if you want to build on it.

Most Recent Post

Configuring Plex on UGreen NAS with Docker and Ansible

Previously I had a plex setup on a dedicated computer in my house, however, I recently purchased a Ugreen NAS, and wanted to migrate plex to the Ugreen machine since it supports docker. Here are the steps to get it working. 1. Install the docker app on the Ugreen. 2. Ensure SSH is enabled, and optionally setup SSH certs (see: https://www.jasonernst.com/posts/2024/07/18/UGreen-NAS-SSH-certs) 2.a Ensure your user is able to access docker, either manually, or via ansible: ``` - name: adding {{ username }} to group docker tags: docker become: true ansible.builtin.user: name: "{{ userna ...