Skip to content

goravel/gateway

Repository files navigation

Gateway

Doc Go Release Test Report Card Codecov License

Microservices can only set grpc endpoints, and the gateway will transform the HTTP request to Grpc request.

Version

goravel/gateway goravel/framework
v1.0.x v1.13.x

Install

  1. Install protoc based on your system

  2. 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
  1. Add package
go get -u github.com/goravel/gateway
  1. Register service provider
// config/app.go
import "github.com/goravel/gateway"

"providers": []foundation.ServiceProvider{
    ...
    &gateway.ServiceProvider{},
}
  1. 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.

  1. 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.

  1. Generate Grpc files

Modify the Makefile file based on your proto files, then run command below:

make -B {your proto name}
  1. 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{},
    },
},
  1. 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 or gateway.Post, etc. to handle the HTTP request.

  1. Add and fill environment variables to .env file
GATEWAY_HOST={gateway host}
GATEWAY_PORT={gateway port}
  1. 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)
    }
}()

Inject variables to the Grpc request

Imagine, you have two endpoints:

  1. POST /login: login in your system and return a JWT token.
  2. 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())

An example: https://github.com/goravel-ecosystem/market-backend/blob/master/src/go/gateway/app/http/middleware/jwt.go

Testing

Run command below to run test:

go test ./...