~ols/blog.ols.wtf

e43b880b2f292b3cf2053ab44b111c4feccb9ad3 — Oliver Leaver-Smith 1 year, 7 months ago 8374b40
Add whois-api blog
1 files changed, 52 insertions(+), 0 deletions(-)

A src/whois-api.md
A src/whois-api.md => src/whois-api.md +52 -0
@@ 0,0 1,52 @@
# Writing a personal whois API
## Making use of Golang, Lambda, and API Gateway

A while back I wrote a `whois` API to contain some basic information about me. It was written in Node.JS, and had different JSON responses based on the path you requested (e.g. `/name`, `/job`, etc.). The code is [here](https://git.sr.ht/~ols/whois.ols.wtf/tree/master/app.js) if you are interested in how the first iteration of this project worked. It was hosted on an intentionally-unnamed SaaS provider that just wasn't up to scratch.

Every two weeks at $dayjob, we get the day to work on our own projects, with the expectation to learn and develop yourself and your skills. This time, I decided that I would rewrite my  `whois` API as a Lambda function written in Go, and put it behind AWS' API Gateway product.

I knew this time round that I wanted to just return a load of JSON on `/`, rather than split it up into different paths. I started writing it out as an anonymous struct but that started to become unwieldy quite quickly:

```
json.Marshal(struct {
        Name  string
        ContactDetails struct {
            Mobile string
            Landline string
        }
    }{Name: "Oliver Leaver-Smith", ContactDetails: struct {
        Mobile string
        Landline string
    }{Mobile: "+447450217558", Landline: "+1143601337"}}
```

I quickly realised that this was going to get ridiculous as the JSON response became more complex, so I turned to my trust Golang resource [Tomy](https://twitter.com/_tmus) for assistance. He reminded me that it would be better to make a type and then set the fields of a new instance of this type, which would be a lot cleaner. A snippet of this looks as follows:

```
type jsonPayload struct {
    PersonalDetails struct {
        Name struct {
            Fullname struct {
                Canonical string
                Preferred string
            }
        }
    }
}

values := jsonPayload{}

values.PersonalDetails.Name.Fullname.Canonical = "Oliver John Leaver-Smith"
values.PersonalDetails.Name.Fullname.Preferred = "Oliver Leaver-Smith"
```

I have used [serverless](https://serverless.com) a few times in the past for little Lambda projects, so thought I would go the same route this time too. Serverless will automatically create your Lambda and everything required to run it, including the API gateway. It also has some handy docs about how to use the Golang AWS Lambda handlers in your application.

The API Gateway endpoint that you are provided by Serverless is a bog-standard AWS one with a URL as long as your arm. I wanted to shorten it. Thankfully, I had already delegated DNS authority of a subdomain `api.ols.wtf` to Route53, and so I could easily use that custom domain for the API Gateway endpoint. I went with `/whois`, and removed the requirement to send an API key as a header, and there it was—available to the world.

```
$ curl -s https://api.ols.wtf/whois | jq -r .About
This is a simple application to display my "whois". It includes all the details you should need in order to get in touch with me, and also to decide if you actually want to. It is as Lambda function hosted in AWS, behind their API Gateway product, available the domain https://api.ols.wtf/whois (but as you're here, you probably already knew that). The code is hosted here: https://git.sr.ht/~ols/whois
```

The new code is available [here](https://git.sr.ht/~ols/whois), my next job is to get some automation around deployments of the API, but that is probably for another day.