Awesome
What is protoc-gen-echo?
protoc-gen-echo
is a protoc plug-in that generates Echo server code
from proto file.
If you want to create a Echo's http api
/helloworld/:name/hi/:nice
, you just need to add rpc in a proto file, and generate it.
/helloworld/:name/hi/:nice
mapping http api will be generated by protoc-gen-echo
.
protoc-gen-echo
can generate complete backend all code combination with protoc-gen-ent.
** About ent you can find more help from ent.
Quick start
Step 0: Pre-installation on ubuntu
sudo apt install protobuf-compiler make
Step 1: Edit ./example/v1/greeter.proto
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/helloworld/{name}/hi/{nice}"
};
}
//...
}
//...
Step 2: Generate
You can generate code used by make
:
make example
Or you can generate code used by below too:
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install github.com/go-woo/protoc-gen-echo@latest
protoc --proto_path=. \
--proto_path=./third_party \
--go_out=paths=source_relative:. \
--echo_out=paths=source_relative:. \
./example/v1/greeter.proto
The protoc-gen-echo
generated 2 files:greeter_router.pb.go
and greeter_handler.pb.go
.
The greeter.pb.go
was generated by protoc-gen-go
More help can be found in protoc.
Your business logic stubs has been generated in your_xxxx_handler.pb.go
,
You can edit business logic in stubs.
func $(YourService)$(RpcName)BusinessHandler(payload *YourRequest) (YourReply, error) {
// Here can put your business logic, can use ORM:github.com/go-woo/protoc-gen-ent
return YourReply{}, nil
}
All handlers typo can be found in your_xxxx_router.pb.go
.
Step 3: Write example business logic
For this example, in greeter_router.pb.go
.
You can find generated echo's handler _Greeter_SayHello0_HTTP_Handler
.
func RegisterGreeterRouter(e *echo.Echo) {
e.GET("/helloworld/:name/hi/:nice", _Greeter_SayHello0_HTTP_Handler)
//...
}
In same file, you can find _Greeter_SayHello0_HTTP_Handler
's implement:
func _Greeter_SayHello0_HTTP_Handler(c echo.Context) error {
var req *HelloRequest = new(HelloRequest)
req.Name = c.Param(strings.ToLower("Name"))
req.Nice = c.Param(strings.ToLower("Nice"))
reply, err := GreeterSayHelloBusinessHandler(req, c)
if err != nil {
return err
}
return c.JSON(http.StatusOK, &reply)
}
Our focus is on GreeterSayHelloBusinessHandler(payload)
.
In greeter_handler.pb.go
, you can write business logic.
func GreeterSayHelloBusinessHandler(req *HelloRequest, c echo.Context) (HelloReply, error) {
// Here can put your business logic,protoc-gen-ent soon coming
reqJson, err := json.Marshal(req)
if err != nil {
return HelloReply{}, err
}
fmt.Printf("Got HelloRequest is: %v\n", string(reqJson))
return HelloReply{}, nil
}
For running this example we need to write a main.go
package main
import (
v1 "github.com/go-woo/protoc-gen-echo/example/v1"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
v1.RegisterGreeterRouter(e)
// you can add custom router outside protoc-gen-echo too.
// MyCustomRouter(e)
e.Logger.Fatal(e.Start(":1323"))
}
More help and doc can be found on Echo , include rate limited, auto update TLS cert, etc.
Step 4: Run example
cd example && go run main.go
Open browser, URL:http://localhost:1223/helloworld/Lok-Tar/hi/Ogar
Or shell execute
curl -X GET http://localhost:1323/helloworld/Lok-Tar/hi/Ogar
Step 5: Optional JWT support
Service option
//get token URL
option (google.api.default_host) = "/login";
//need auth root path, can multi path
option (google.api.oauth_scopes) =
"/restricted,"
was used for JWT describer.
If you want to support JWT, can add it. Else you can comment it.
:bangbang: Special notes
-
Do not remove
your_xxxx_handler.pb.go
. It was generated only when the first time, and will not be generated or overwritten after that again, because the business logic code you added is already in it. -
JSON format in http body. If http client request has body, header should has
Content-Type: application/json
-
Validate. Single source(proto) is the most important means to ensure consistency. protobuf message filed validate can use protoc-gen-validate.
-
protoc-gen-echo
follow google.api.httprule. -
ent still does not support message nesting, so proto http rule body must be *.
Generate gRPC
gRPC generated by protoc-gen-go-grpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
Add --go-grpc_out=paths=source_relative:. \
protoc --proto_path=. \
--proto_path=./third_party \
--go_out=paths=source_relative:. \
--echo_out=paths=source_relative:. \
--go-grpc_out=paths=source_relative:. \
./example/v1/greeter.proto
Generate Open Api Spec document
OAS generated by protoc-gen-openapi
go install github.com/google/gnostic/cmd/protoc-gen-openapi@latest
Add --openapi_out=paths=source_relative:. \
protoc --proto_path=. \
--proto_path=./third_party \
--go_out=paths=source_relative:. \
--echo_out=paths=source_relative:. \
--openapi_out=paths=source_relative:. \
./example/v1/greeter.proto
Generated yaml file can be browser on swagger or openapi
Validate
Fields validate generated by protoc-gen-validate
go install github.com/envoyproxy/protoc-gen-validate@latest
Add --validate_out="lang=go:." \
protoc --proto_path=. \
--proto_path=./third_party \
--go_out=paths=source_relative:. \
--echo_out=paths=source_relative:. \
--validate_out="lang=go:." \
./example/v1/greeter.proto
Todo
- Add generate jwt openapi/swagger support
https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#securitySchemeObject
https://github.com/grpc-ecosystem/grpc-gateway/blob/master/examples/internal/proto/examplepb/a_bit_of_everything.proto