gRPC and Server Side Swift: Getting Started
Learn how to define an API with gRPC and how to integrate it in a Vapor application. By Walter Tyree.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
gRPC and Server Side Swift: Getting Started
35 mins
- Getting Started
- Installing Evans
- Installing Protoc and the Swift Plugins
- Adding gRPC Support to Vapor
- Learning About gRPC
- How is gRPC Different from REST?
- Learning the Difference Between gRPC and JSON?
- Working with a .proto File
- Defining the Services
- Defining the Messages
- Exercising a .proto File With Evans
- Generating Swift Code From a .proto file
- Messages Become Structs
- Working with Generated Code
- Turning Services Into Functions
- Implementing Service Functions
- Replacing the HTTP Server in Vapor
- Configuring the gRPC Server
- Using the gRPC Server
- Trying out the App
- Changing the API
- Updating the Spec
- Adding the Completion Logic
- Updating the Database Model
- Where to Go from Here?
Learning the Difference Between gRPC and JSON?
For encoding and decoding data objects, gRPC uses Protocol Buffers.
Unlike the plain text files used by JSON, Protocol Buffers are a binary file type, not human readable. They enable the exchange of smaller payloads, which are more efficient and suitable for low bandwidth use cases.
To get started, you must define gRPC messages and data models in a .proto file.
Working with a .proto File
A .proto file is a text file containing definitions for all your APIs. In this tutorial the domain revolves around Messages and Services. Messages are the data objects that get sent between the client and server. Services define how messages get transported. A .proto file can also have some metadata to help the various code generators.
Most exciting to anyone who has ever struggled with comments in JSON: a .proto file can have comments! It supports both //
style and /* ... */
style comments!
Open the todo.proto file in the root directory of the project to explore it a bit. The first line of the file specifies the version of gRPC to use. It looks like this:
syntax = "proto3";
If this line is missing, the gRPC system will assume that you’re using version 2, not version 3. After that, some options will assist the code generator in naming things.
Defining the Services
Next, you’ll see the service definition. The rpc
entries will each become a func
in the generated Swift code.
// The todos service definition.
service TodoService {
// Return a list of todos.
rpc FetchTodos (Empty) returns (TodoList) {}
// Create a new todo
rpc CreateTodo (Todo) returns (Todo) {}
// Delete a todo
rpc DeleteTodo (TodoID) returns (Empty) {}
}
Adding code to every generated func
is how you’ll make the server work. Every rpc
must have a request and a response message. That’s why FetchTodos
sends an Empty
message rather than something like FetchTodos()
.
Defining the Messages
Here is the message spec for the Todo
object:
message Todo {
optional string todoID = 1;
string title = 2;
}
This code defines two fields; title
and todoID
. It also ensures that they’re of type string
.
The first field is marked as optional
. It won’t have a value until it’s been stored in the database. The code generator keeps track of each field in a message by assigning it a number.
In addition to the string
type, a field can be many different scalar types and each language generator will make the appropriate translations. Fields can be enumerations or even other messages. For example, below is the definition of TodoList
, which is a collection of Todo
instances.
message TodoList {
repeated Todo todos = 1;
}
The repeated
keyword means that the code will generate an array of Todo
s. You can learn more about the different options in the proto3 language guide.
Google provides many well-known types including: Empty
, Timestamp
, BoolValue
and many more. You can read the documentation to learn about them. Since the homebrew
version of protoc
isn’t bundled with them, this tutorial uses a custom one. Both strategies, using Google’s or making your own, are common.
Exercising a .proto File With Evans
In a Terminal window, navigate to the root directory of the project. This is the directory that contains the todo.proto file. Launch Evans in REPL mode using this command:
evans repl --host localhost --port 1234 --proto ./todo.proto
You’ll see the Evans prompt, similar to this:
______
| ____|
| |__ __ __ __ _ _ __ ___
| __| \ \ / / / _. | | '_ \ / __|
| |____ \ V / | (_| | | | | | \__ \
|______| \_/ \__,_| |_| |_| |___/
more expressive universal gRPC client
todos.TodoService@localhost:1234>
Even though you don’t have a running gRPC server yet and haven’t generated the gRPC Swift code, Evans uses the todo.proto file to provide information about the services.
Recall from the todo.proto file that you have four messages: Empty
, Todo
, TodoList
and TodoID
. The file also defines three services: FetchTodos
, CreateTodo
and DeleteTodo
. Use Evans to inspect these.
Now type the following command in the Evans prompt:
show message
You’ll see the four defined messages, like this:
+----------+
| MESSAGE |
+----------+
| Empty |
| Todo |
| TodoID |
| TodoList |
+----------+
Now type show service
to see the list of services. Evans will show:
+-------------+--------------+--------------+---------------+
| SERVICE | RPC | REQUEST TYPE | RESPONSE TYPE |
+-------------+--------------+--------------+---------------+
| TodoService | FetchTodos | Empty | TodoList |
| TodoService | CreateTodo | Todo | Todo |
| TodoService | DeleteTodo | TodoID | Empty |
+-------------+--------------+--------------+---------------+
To close Evans and return to Terminal type: exit
.
You are on the right track. The next step is to generate some Swift code.
Generating Swift Code From a .proto file
Make sure Terminal is in the directory with the todo.proto file and type the following:
protoc --swift_out=Sources/App/Models/ --grpc-swift_out=Sources/App/Controllers/ todo.proto
This command will create two files: Sources/App/Models/todo.pb.swift and Sources/App/Controllers/todo.grpc.swift. The first is for the Message
items, the second is for the Service
items. You’ll not be editing these files directly, and whenever the API changes, you’ll need to regenerate them. If the files don’t appear in your IDE, you may need to close and reopen the project to refresh the list of files.
There are a number of other options available but the ones specified above will generate the two swift files for this tutorial.
grpc-swift
plugin does not create async/await code by default and does not yet officially support async/await. One of the options for protoc
will generate async/await style code based on a proposed implementation. You can read more about this option and the async/await code at the GitHub repository for the project.