Image Resizing with Go and Cloud Functions
Google Cloud Platform now supports Go 1.11 for Cloud functions. Go and Serverless are 2 things I’m very excited about these days so I decided to give this new GCP feature a try and build a basic Image Resizer in pure Go using the disintegration/imaging package.
Sometimes you just have gopher images that are too large to display on your website. They would eat up the precious bandwidth of your users ! Like this massive one:
So we’ll be transforming it into this smaller, more reasonable gopher:
What we’ll build in order to achieve this is a cloud function with an endpoint that can be called in the following way:
We just send an HTTP GET request with our image url, the desired width and height and we receive an image in JPEG format in the HTTP response body.
To follow along, you’ll need to have Go 1.11 installed on your dev box, a Google Cloud Platform account and the gcloud command line tool setup.
I’ve setup a github repo if you would like to browse it/clone it locally and test as you’re reading.
The ResizeImage cloud function
The cloud function we’ll use is an HTTP function. This cloud function type gives us an HTTPS endpoint for our code without needing an extra API Gateway so that’s pretty convenient for our use case. The other cloud function type: Background functions can be triggered by events such as Pub/Sub or Cloud Storage events. We won’t be using this today but it could come in handy for other tasks such as caching our images, cleaning up the cache periodically etc. I might write about Background functions in a future article.
The ResizeImage function needs to do the following things:
- Parse the Query string into url, height and width
- Fetch the original image
- Resize the image
- Encode the output image to Jpg
- Write the encoded output image to the HTTP Response stream
To keep things simple I’ve included all the code in a single file. The filename doesn’t matter.
I’ve also included a go.mod file with the dependencies as that’s supported.
To push all this to the cloud, we use the gcloud tool and specify the name of the function that we want to deploy. In this case it’s this go function:
ResizeImage(w http.ResponseWriter, r *http.Request)
The ResizeImage function in the code above has the correct signature so it can be deployed. You’ll notice that it’s just a http.HandlerFunc from the Go standard library.
$ gcloud functions deploy ResizeImage --runtime go111 --trigger-httpDeploying function (may take a while - up to 2 minutes)...done.
Our function is deployed and we get the endpoint url in return. Big gopher images here we come !
To test this code as I was writing it, I’ve used a local development server to run the handler. During development, it would be pretty inconvenient to redeploy each time I make a small change to test and I also couldn’t find a local Golang cloud functions emulator (There is a node.js emulator, so hopefully a Go version is planned ?). However, the setup with a local server worked out pretty well for this simple function.
This a simple example but hopefully it can help you to get started with Golang on Cloud Functions. If we wanted to make this project production-ready here are some examples of the next steps we could take:
- Add Unit tests
- Cache the input images
- Cache the output images
- Add Authentication
- Benchmark resizing libraries to find the fastest alternative
Thanks for reading and happy resizing !
Github Repo: https://github.com/didil/gcf-go-image-resizer