Supporting REST and HTML with a gRPC Microservice

Any microservice can become a gRPC microservice. gRPC and protobuf work together to bring more structure to building out APIs, even if your service has to work across different clients or support streams of data. The system generates model and networking code for the protocol — you define the API using a .proto file which […] By Walter Tyree.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Adding a Transcoding Filter

The first filter you need to set up is the transcoding filter. Its important keys are name and typed_config, and they signal that your filter is a gRPC to HTTP/JSON transcoder.

Your first step is to tell the filter about your API.

Set the proto_descriptor to the file path of todo.pb. Additionally, set the services to the name of your service in the todo.proto file.

Your finished entry should look like this:

proto_descriptor: "data/todo.pb"
services: ["todos.TodoService"]

Leave the other values in this section as their defaults, but there are a couple of items to note:

  • Scroll down to the definition for clusters. At the end, you’ll find an entry for address: host.docker.internal, which is something you need when running Envoy in Docker as you are right now.
  • Your gRPC server port value is set to 1234, so no need to make changes there.

Running the Servers

If your servers aren’t running, use Docker commands to start them. And even if your Envoy server is running, bring it up again to reload the configuration files you have just modified. Open a new Terminal, navigate to the starter project root directory and enter the following commands:

docker compose up db -d
docker compose up app -d
docker compose up envoy -d

These commands bring up your application containers again, re-reading their configuration files to pick up any changes.

Now that the configurations are set, you should be able to send gRPC or HTTP traffic to port 8082. The requests will get rerouted to your gRPC server.

The next step is to use Postman to send a GET request to localhost:8082/v1/todos. If you created any TODOs earlier they should appear. Otherwise, you’ll recieve an empty JSON array.

The animated screenshot below shows retrieving the Todo list, creating a Todo, completing a Todo, and deleting a Todo with Postman.
Listing, adding, completing, and removing Todos with Postman

If you’ve installed Evans you can now use it with port 8082.

Envoy routes both kinds of traffic — gRPC traffic passes through to the server untouched, and HTTP traffic gets transcoded.

Now do it: To point Evans to the new port, change the command from before:

evans repl --host localhost --port 8082 --proto ./todo.proto

Now Evans knows to use the new port you created.

Other Options with protoc

Swift server code is moving from using Futures based on SwiftNIO to Async/Await. Recently, the grpc-swift team updated the protoc plugins to generate both code patterns.

In the next few sections, you’ll learn how to switch to Async/Await patterns in your concurrency code.

Generating Concurrency Code

In this tutorial, the grpc-swift plugin uses EventLoopFuture but not the Async/Await concurrency pattern. You can ignore part of the documentation at the repo.

In the past either ExperimentalAsyncClient or the ExperimentalAsyncServicer flag could generate experimental Aysnc/Await code, but neither currently work.

In Spring of 2022, Async/Await support was moved to a different branch, but was merged back to main in the Summer.

With these updates to the plugins, you don’t need to provide any special options or flags. They generate Async/Await code and the SwiftNIO style code.

Starting with the release of grpc-swift 1.8 in June 2022, generated .swift files no longer use the same naming convention for Swift compilers 5.6 and above for clients. For servers, the SwiftNIO naming convention is the same.

To take advantage of the Async/Await structure, new implementations are available to you. For example, consider the code generated by the todo.proto:

For Swift 5.5 and older compilers, the service provider is `Todos_TodoServiceProvider`

For Swift 5.6 and newer compilers, the SwiftNIO service provider is `Todos_TodoServiceProvider`. Additionally a `Todos_TodoServiceAsyncProvider` protocol appears in the todo.grpc.swift file.

The signature of the fetchTodos changes from:

func fetchTodos(request: Todos_Empty, context: StatusOnlyCallContext) -> EventLoopFuture<Todos_TodoList>

To this:

func fetchTodos(request: Todos_Empty, context: GRPCAsyncServerCallContext) async throws -> Todos_TodoList

Though this tutorial doesn’t focus on writing Swift Service Clients, there is similar change worthy of note.

For 5.6 and later compilers, any instances of `Todos_TodoServiceClient` will be marked as deprecated and will use the SwiftNIO code.

In order to continue using SwiftNIO style code, you need to change instances of `Todos_TodoServiceClient` to `Todos_TodoServiceNIOClient`.

To switch to Async/Await, update your client code to use `Todos_TodoServiceAsyncClient`.

This part of the grpc-swift project is under active development. Be sure to check the repository and GitHub if you encounter issues or unexpected warnings as you work.

Where to Go from Here?

Download the completed project files by clicking the Download Materials button at the top or bottom of this tutorial.

In this tutorial you learned a few things:

  • How to generate a protocol definition file that mapped HTTP URLs to gRPC services.
  • How to configure an Envoy proxy to transcode HTTP/JSON to gRPC.
  • How to use some of the optional features of the protoc command.

Now you’re well-equipped to enable services to use multiple protocols at the same endpoint. You can upgrade your servers to enjoy more efficient communication with new clients, without forcing your older applications to update. This means that existing REST clients, like web front ends or iOS applications, don’t need to be changed. Your back end applications can now support gRPC clients seamlessly.

Visit the Envoy documentation website to access the full documentation for how to configure Envoy to transcode HTTP/gRPC.

You can also find the main documentation for Envoy on that same site.

Over on Github, the grpc-swift project contains information about support for Async/Await, and it has the full documentation for the Swift plugin and its options.

Finally, Google offers guidance for designing APIs that support gRPC and HTTP transcoding.

We hope you enjoyed this tutorial. Please join the forum discussion below if you have any questions or comments!

Contributors

Nate Schaffner

Tech Editor

Wendy L

Editor

Adriana Kutenko

Illustrator

Darren Ferguson

Final Pass Editor

Catie Catterwaul

Team Lead

Over 300 content creators. Join our team.