Microservices can only set grpc endpoints, and the gateway will transform the HTTP request to Grpc request.
goravel/gateway | goravel/framework |
---|---|
v1.0.x | v1.13.x |
-
Install protoc based on your system
-
Install Grpc Gateway plugin to your system
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2
- Add package
go get -u github.com/goravel/gateway
- Register service provider
// config/app.go
import "github.com/goravel/gateway"
"providers": []foundation.ServiceProvider{
...
&gateway.ServiceProvider{},
}
- Publish config and proto files
go run . artisan vendor:publish --package=github.com/goravel/gateway
This method will publish the config/gateway.go
file and the proto
folder to your project.
- Add Grpc endpoints
Rename the proto/example/example.proto
file and add your Grpc endpoints. Notice, you should add option (google.api.http)
to your endpoints like the example, you can get more examples in the proto/google/api/http.proto
file.
- Generate Grpc files
Modify the Makefile
file based on your proto files, then run command below:
make -B {your proto name}
- Configure Grpc Clients
Modify the config/grpc.go
file to add your Grpc clients. Notice, you should add handlers
to your clients like the example.
"clients": map[string]any{
"example": map[string]any{
"host": config.Env("GRPC_EXAMPLE_HOST", ""),
"port": config.Env("GRPC_EXAMPLE_PORT", ""),
// A new configuration from the gateway package, `example.RegisterUsersServiceHandler` is come from the
// `proto/example/example.pb.gw.go` file that generated by the make command.
"handlers": []gateway.Handler{example.RegisterUsersServiceHandler},
"interceptors": []string{},
},
},
- Add HTTP endpoints
Add all HTTP route that define in the proto/example/example.proto
file to the routes/api.go
file, like the example below:
import "github.com/goravel/gateway"
func Api() {
facades.Route().Post("/users/{id}", gateway.Get)
facades.Route().Post("/users", gateway.Post)
}
Notice, you should use
gateway.Get
orgateway.Post
, etc. to handle the HTTP request.
- Add and fill environment variables to
.env
file
GATEWAY_HOST={gateway host}
GATEWAY_PORT={gateway port}
- Run HTTP server and Gateway
import (
"github.com/goravel/framework/facades"
gatewayfacades "github.com/goravel/gateway/facades"
)
go func() {
if err := facades.Route().Run(); err != nil {
facades.Log().Errorf("Route run error: %v", err)
}
}()
go func() {
if err := gatewayfacades.Gateway().Run(); err != nil {
facades.Log().Errorf("Gateway run error: %v", err)
}
}()
Imagine, you have two endpoints:
POST /login
: login in your system and return a JWT token.POST /users
: create a user, needs a JWT token to authorize, the request of the corresponding Grpc endpoint is:
message CreateUserRequest {
int32 user_id = 1;
string name = 2;
int32 age = 3;
}
message CreateUserResponse {
Status status = 1;
User user = 2;
}
rpc CreateUser (CreateUserRequest) returns (CreateUserResponse) {
option (google.api.http) = {
post: "/users"
body: "*"
};
}
The user_id
in the request is parsed by the JWT token, it's terrible if parse it in every Grpc endpoint, In addition,
if the CreateUser
Grpc endpoint can be called by other microservices directly, other microservices should pass the
user_id
instead of a JWT token, so we should add an HTTP middleware to parse the JWT token and inject the user_id
to
the Grpc request.
import "github.com/goravel/gateway"
gateway.Inject(ctx, "user_id", user.GetId())
Run command below to run test:
go test ./...