Building Reverse Proxy (gRPC-Gateway) | by Yair Fernando | Oct, 2022

gRPC API with protocol buffers

combined image by author | right image by traefik, left image by Go

In the last article, we built the API design for a social media application. We wrote the definition of five REST endpoints for a Post using Protocol Buffers as well as the HTTP annotations for each endpoint, we also generated the code to implement a reverse proxy using the grpc-gateway plugin.

In this article, we’ll continue building the API and the next step is implementing the reverse proxy.

If you missed the last article, I’d recommend reading the articles in the following order:

  1. Go API Design With Protocol Buffers and gRPC
  2. Building Reverse Proxy (gRPC-Gateway)

We’ll be using docker and docker-compose, so I recommend installing docker and docker-compose first and make sure you are able to run containers.

Navigate to your GOPATH, if you don’t know what’s your go path directory, you can run echo $GOPATH and that will print the correct path. In there create the src/github/com/yaairfernando folder structure, replacing the last directory with your GitHub handle. Once you are there, create the following project structure:

mkdir socialMedia
cd socialMedia
touch docker-compose.yaml

All right, let’s start by defining the docker-compose yaml file.

From the above yaml file, we are defining the proxy service, from the configuration of this service we can see that the container name is proxy, and the image that will use is sma:proxy, in case the docker image does not exist, it will build it from the ./proxy folder, we are also passing as arguments a GitHub access token, this is only necessary if you created a private repo for the API design from the previous article.

If so, you’ll need to pass a GitHub access token to the docker image to be able to access private repositories from the docker file.

We also specify a command and two environment variables to be run: one to specify the rest port where the server will be running, and a grpc URL, which points to the service that the proxy will be proxying requests.

We also specify that the port that this service will expose is 9094 and internally would be 8081.

Let’s now create a proxy folder and the main.go file:

mkdir proxy
cd proxy
touch main.go

Inside the proxy folder, we’ll run this command to create a go module

go mod init

This will create a go.mod file under the proxy folder.

module 1.18

The main.go file looks like this:

The main function is only initializing a new server passing the grpcURL, restPort, and calling the start method on the server instance.

Let’s see what the server file looks like. Create the server folder and a server.go file.

mkdir server
cd server
touch server.go

This server file has all the logic to register the handler for the Posts resource, add a simple logger, create an HTTP server and listen on the specified port.

  • In line 36 we create a new server mux
  • In line 38, we wrapped that server with a simple logger
  • In line 40, we register all the handlers. In our case, we only have one for the Posts resource at the moment
  • Lastly, in lines 45–49 we create an HTTP server passing the handler and start listening

As you can see, some helper functions are not defined in this file. I added them to a utils file.

All right, let’s now create the Dockerfile:

I will not go deep into what this docker file is doing, but essentially it uses a Golang image as the builder, sets some go environment variables, sets the working directory, and copies the go.mod file. After that, it downloads all dependencies, copies the rest of the files, and lastly, sets the entry point.

This is the go.mod file with all the packages that are used.

This is the final folder structure for the project:

We are almost done. Now, let’s download the go packages we need by running the following commands in the proxy folder:

go mod download
go mod tidy

As you can see for the sma package, we specified that we want version v0.1.0 from that package, but when we built the API design we did not create any versions. Let’s do that.

Generate Git tag

Go back to where you have the sma project, and let’s create a tag:

git tag v0.1.0

And push it to the repository:

git push origin v0.1.0

Now, back in the proxy folder, run this command to download that version of the sma package:

go get

The above command will download the sma package with the specified version.

We can now build the proxy service by running:

docker-compose up --build -d proxy

When running this command you’ll get some errors saying to download some packages that we have specified in the go.mod file. Just download the packages by running go mod download package_path. And re-run the docker-compose command.

After the build finishes, we should be able to see the container running. Sending a POST request to http://localhost:9094/v1/postswill not work yet, but we can see the log.

Proxy Running

That is all for this article. We have implemented the reverse proxy. In the next article, we’ll continue building the API.

Stay tuned, and thank you for reading!

News Credit

%d bloggers like this: