Image Resizing with Go and Cloud Functions
Tags: gcp, go, serverless, imageprocessing
Published: 2019-01-18 12:33:16

---
title: Image Resizing with Go and Cloud Functions
published: true
tags: gcp,golang,serverless,image-processing
canonical_url: https://medium.com/@didil/image-resizing-with-go-and-cloud-functions-792a47e6473d
---

#### Go + Serverless = ❤️

Google Cloud Platform now [supports Go 1.11 for Cloud functions](https://cloud.google.com/blog/products/application-development/cloud-functions-go-1-11-is-now-a-supported-language). 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](https://github.com/disintegration/imaging) package.

#### Resizing gophers

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:

![](https://cdn-images-1.medium.com/max/1024/1*k74qnaAcJd3bzRj7PnLIbg.jpeg)<figcaption>Big gopher generated using gopherize.me</figcaption>

So we’ll be transforming it into this smaller, more reasonable gopher:

![](https://cdn-images-1.medium.com/max/289/1*XHNGwmff9RaxUtRkVaggXA.jpeg)<figcaption>Small gopher</figcaption>

What we’ll build in order to achieve this is a cloud function with an endpoint that can be called in the following way:

_https://{region}-{project-name}._cloudfunctions.net/ResizeImage?_url={url}&height={height}&width={width}_

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.

#### Setup

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](https://cloud.google.com/functions/docs/quickstart#functions-update-install-gcloud-go).

I’ve setup a [github repo](https://github.com/didil/gcf-go-image-resizer) 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.

{% gist https://gist.github.com/didil/8bb6e9c2a81f348a06218420e3b6094a %}

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](https://golang.org/pkg/net/http/#HandlerFunc) from the Go standard library.

```
_$ gcloud functions deploy ResizeImage --runtime go111 --trigger-http_

Deploying function (may take a while - up to 2 minutes)...done.                                                                                                                                                                
availableMemoryMb: 256
entryPoint: ResizeImage
httpsTrigger:
  url: [https://xxx.cloudfunctions.net/ResizeImage](https://us-central1-gcf-go-image-resizer.cloudfunctions.net/ResizeImage)
```

Our function is deployed and we get the endpoint url in return. Big gopher images here we come !

#### Local development

To test this code as I was writing it, I’ve used a [local development server](https://github.com/didil/gcf-go-image-resizer/blob/master/cmd/server/server.go) 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](https://cloud.google.com/functions/docs/emulator), so hopefully a Go version is planned ?). However, the setup with a local server worked out pretty well for this simple function.

####  Next Steps
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](https://github.com/fawick/speedtest-resize) to find the fastest alternative

Thanks for reading and happy resizing !

_Github Repo:_ [_https://github.com/didil/gcf-go-image-resizer_](https://github.com/didil/gcf-go-image-resizer)