-
Notifications
You must be signed in to change notification settings - Fork 277
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add documentation for creating gRPC Handlers through gofr-cli (#1383)
- Loading branch information
1 parent
53e8b7a
commit 9e01054
Showing
6 changed files
with
275 additions
and
142 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,125 +1,142 @@ | ||
# gRPC | ||
We have already seen how GoFr can help ease the development of HTTP servers, but there are | ||
cases where performance is primarily required sacrificing flexibility. In these types of | ||
scenarios gRPC protocol comes into picture. {% new-tab-link title="gRPC" href="https://grpc.io/docs/what-is-grpc/introduction/" /%} is an open-source RPC(Remote Procedure Call) | ||
framework initially developed by Google. | ||
# gRPC with Gofr | ||
|
||
We have already seen how GoFr can help ease the development of HTTP servers, but there are cases where performance is primarily required sacrificing flexibility. In these types of scenarios gRPC protocol comes into picture. {% new-tab-link title="gRPC" href="https://grpc.io/docs/what-is-grpc/introduction/" /%} is an open-source RPC(Remote Procedure Call) framework initially developed by Google. | ||
|
||
GoFr enables you to create gRPC handlers efficiently while leveraging GoFr's context support for seamless access to connected datasources and trace management within your handlers. | ||
|
||
## Prerequisites | ||
- Install the `protoc` protocol buffer compilation | ||
- Linux, using `apt` or `apt-get` | ||
```shell | ||
$ apt install -y protobuf-compiler | ||
$ protoc --version # Ensure compiler version is 3+ | ||
``` | ||
- macOS, using Homebrew | ||
```shell | ||
$ brew install protobuf | ||
$ protoc --version # Ensure compiler version is 3+ | ||
``` | ||
- Install **Go Plugins** for protocol compiler: | ||
1. Install protocol compiler plugins for Go | ||
```shell | ||
$ go install google.golang.org/protobuf/cmd/[email protected] | ||
$ go install google.golang.org/grpc/cmd/[email protected] | ||
``` | ||
2. Update `PATH` for `protoc` compiler to find the plugins: | ||
```shell | ||
$ export PATH="$PATH:$(go env GOPATH)/bin" | ||
``` | ||
|
||
## Creating protocol buffers | ||
For a detailed guide, please take a look at the {% new-tab-link title="Tutorial" href="https://grpc.io/docs/languages/go/basics/" /%} at official gRPC docs. | ||
|
||
We need to create a `customer.proto` file to define our service and the RPC methods that the service provides. | ||
```protobuf | ||
// Indicates the protocol buffer version that is being used | ||
syntax = "proto3"; | ||
// Indicates the go package where the generated file will be produced | ||
option go_package = ""; | ||
|
||
service CustomerService { | ||
// ... | ||
} | ||
``` | ||
Inside the service one can define all the `rpc` methods, specifying the request and responses types. | ||
```protobuf | ||
service CustomerService { | ||
// GetCustomer is a rpc method to get customer data using specific filters | ||
rpc GetCustomer(CustomerFilter) returns(CustomerData) {} | ||
} | ||
``` | ||
The `CustomerFilter` and `CustomerData` are two types of messages that will be exchanged between server | ||
and client. Users must define those for protocol buffer to serialize them when making a remote procedure call. | ||
```protobuf | ||
syntax = "proto3"; | ||
**1. Protocol Buffer Compiler (`protoc`) Installation:** | ||
|
||
message CustomerFilter { | ||
int64 id = 1; | ||
string name = 2; | ||
// other fields that can be passed | ||
} | ||
- **Linux (using `apt` or `apt-get`):** | ||
```bash | ||
sudo apt install -y protobuf-compiler | ||
protoc --version # Ensure compiler version is 3+ | ||
``` | ||
|
||
message CustomerData { | ||
int64 id = 1; | ||
string name = 2; | ||
string address = 3; | ||
// other customer related fields | ||
} | ||
``` | ||
- **macOS (using Homebrew):** | ||
|
||
Now run the following command to generate go code using the Go gRPC plugins: | ||
```shell | ||
protoc \ | ||
--go_out=. \ | ||
--go_opt=paths=source_relative \ | ||
--go-grpc_out=. \ | ||
--go-grpc_opt=paths=source_relative \ | ||
customer.proto | ||
``` | ||
Above command will generate two files `customer.pb.go` and `customer_grpc.pb.go` and these contain necessary code to perform RPC calls. | ||
In `customer.pb.go` you can find `CustomerService` interface- | ||
```go | ||
// CustomerServiceServer is the server API for CustomerService service. | ||
type CustomerServiceServer interface { | ||
GetCustomer(context.Context, *CustomerFilter) (*CustomerData, error) | ||
} | ||
```bash | ||
brew install protobuf | ||
protoc --version # Ensure compiler version is 3+ | ||
``` | ||
User needs to implement this interface to serve the content to the client calling the method. | ||
```go | ||
package customer | ||
|
||
import ( | ||
"context" | ||
) | ||
**2. Go Plugins for Protocol Compiler:** | ||
|
||
a. Install protocol compiler plugins for Go: | ||
|
||
```bash | ||
go install google.golang.org/protobuf/cmd/[email protected] | ||
go install google.golang.org/grpc/cmd/[email protected] | ||
``` | ||
|
||
b. Update `PATH` for `protoc` to locate the plugins: | ||
|
||
```bash | ||
export PATH="$PATH:$(go env GOPATH)/bin" | ||
``` | ||
|
||
## Creating Protocol Buffers | ||
|
||
For a detailed guide, refer to the official gRPC documentation's tutorial: {% new-tab-link title="Tutorial" href="https://grpc.io/docs/languages/go/basics/" /%} at official gRPC docs. | ||
|
||
**1. Define Your Service and RPC Methods:** | ||
|
||
type Handler struct { | ||
// required fields to get the customer data | ||
Create a `.proto` file (e.g., `customer.proto`) to define your service and the RPC methods it provides: | ||
|
||
```protobuf | ||
// Indicates the protocol buffer version that is being used | ||
syntax = "proto3"; | ||
// Indicates the go package where the generated file will be produced | ||
option go_package = "path/to/your/proto/file"; | ||
service {serviceName}Service { | ||
rpc {serviceMethod} ({serviceRequest}) returns ({serviceResponse}) {} | ||
} | ||
``` | ||
|
||
**2. Specify Request and Response Types:** | ||
|
||
Users must define the type of message being exchanged between server and client, for protocol buffer to serialize them when making a remote | ||
procedure call. Below is a generic representation for services' gRPC messages type. | ||
|
||
```protobuf | ||
message {serviceRequest} { | ||
int64 id = 1; | ||
string name = 2; | ||
// other fields that can be passed | ||
} | ||
func (h *Handler) GetCustomer(ctx context.Context, filter *CustomerFilter) (*CustomerData, error) { | ||
// get the customer data and handler error | ||
return data, nil | ||
message {serviceResponse} { | ||
int64 id = 1; | ||
string name = 2; | ||
string address = 3; | ||
// other customer related fields | ||
} | ||
``` | ||
|
||
Lastly to register the gRPC service to the GoFr server, user can call the `RegisterCustomerServiceServer` in `customer_grpc.pb.go` | ||
to register the service giving GoFr app and the Handler struct. | ||
```go | ||
package main | ||
**3. Generate Go Code:** | ||
|
||
import ( | ||
"gofr.dev/pkg/gofr" | ||
"gofr.dev/examples/grpc-server/customer" | ||
) | ||
Run the following command to generate Go code using the Go gRPC plugins: | ||
|
||
func main() { | ||
app := gofr.New() | ||
```bash | ||
protoc \ | ||
--go_out=. \ | ||
--go_opt=paths=source_relative \ | ||
--go-grpc_out=. \ | ||
--go-grpc_opt=paths=source_relative \ | ||
{serviceName}.proto | ||
``` | ||
|
||
customer.RegisterCustomerServiceServer(app, customer.Handler{}) | ||
This command generates two files, `{serviceName}.pb.go` and `{serviceName}_grpc.pb.go`, containing the necessary code for performing RPC calls. | ||
|
||
app.Run() | ||
} | ||
## Generating gRPC Handler Template using `gofr wrap grpc` | ||
|
||
#### Prerequisite: gofr-cli must be installed | ||
|
||
To install the CLI - | ||
```bash | ||
go install gofr.dev/cli/gofr@latest | ||
``` | ||
|
||
**1. Use the `gofr wrap grpc` Command:** | ||
```bash | ||
gofr wrap grpc -proto=./path/your/proto/file | ||
``` | ||
|
||
This command leverages the `gofr-cli` to generate a `{serviceName}_server.go` file (e.g., `CustomerServer.go`) | ||
containing a template for your gRPC server implementation, including context support, in the same directory as | ||
that of the specified proto file. | ||
|
||
**2. Modify the Generated Code:** | ||
|
||
- Customize the `{serviceName}GoFrServer` struct with required dependencies and fields. | ||
- Implement the `{serviceMethod}` method to handle incoming requests, as required in this usecase: | ||
- Bind the request payload using `ctx.Bind(&{serviceRequest})`. | ||
- Process the request and generate a response. | ||
|
||
## Registering the gRPC Service with Gofr | ||
|
||
**1. Import Necessary Packages:** | ||
|
||
```go | ||
import ( | ||
"gofr.dev/pkg/gofr" | ||
"path/to/your/generated-grpc-server/packageName" | ||
) | ||
``` | ||
|
||
**2. Register the Service in your `main.go`:** | ||
|
||
```go | ||
func main() { | ||
app := gofr.New() | ||
|
||
packageName.Register{serviceName}ServerWithGofr(app, &packageName.{serviceName}GoFrServer{}) | ||
|
||
app.Run() | ||
} | ||
``` | ||
>Note: By default, gRPC server will run on port 9000, to customize the port users can set `GRPC_PORT` config in the .env | ||
> ##### Check out the example of setting up a gRPC server in GoFr: [Visit GitHub](https://github.com/gofr-dev/gofr/blob/main/examples/grpc-server/main.go) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package grpc | ||
|
||
import ( | ||
"fmt" | ||
"gofr.dev/pkg/gofr" | ||
) | ||
|
||
// Register the gRPC service in your app using the following code in your main.go: | ||
// | ||
// grpc.RegisterHelloServerWithGofr(app, &grpc.HelloGoFrServer{}) | ||
// | ||
// HelloGoFrServer defines the gRPC server implementation. | ||
// Customize the struct with required dependencies and fields as needed. | ||
|
||
type HelloGoFrServer struct { | ||
} | ||
|
||
func (s *HelloGoFrServer) SayHello(ctx *gofr.Context) (any, error) { | ||
request := HelloRequest{} | ||
|
||
err := ctx.Bind(&request) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
name := request.Name | ||
if name == "" { | ||
name = "World" | ||
} | ||
|
||
return &HelloResponse{ | ||
Message: fmt.Sprintf("Hello %s!", name), | ||
}, nil | ||
} |
Oops, something went wrong.