
Kratos 官方提供了 protoc-gen-go-http 插件,该插件根据 .proto 文件中的 google.api.http option,生成 HTTP handler、路由注册代码、参数绑定逻辑。
与 grpc-gateway 不同,protoc-gen-go-http 并不需要额外的“网关”层。它直接在服务端生成原生的 http.Handler,让 gRPC 服务天然具备 REST 能力。
02google.api.http option 详解
google.api.http option 是 Google API 的一个 Protobuf 扩展,用来把 gRPC 方法映射为 HTTP REST 接口。
syntax = "proto3";
package helloworld.v1;
import"google/api/annotations.proto";
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/helloworld/{name}"
// 可以添加附加接口
additional_bindings {
// 定义一个 POST 接口,并且把 body 映射到 HelloRequest
post: "/v1/greeter/say_hello",
body: "*",
}
};
}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
阅读上面这段代码,我们可以在 .proto 文件中添加 google.api.http option,其中,get: "/helloworld/{name}" 是把 name 映射到 URL 路径参数,即 /helloworld/frank;
post: "/v1/greeter/say_hello" 定义一个 POST 请求方式的 API,body: "*" 代表整个请求体(JSON)映射到 HelloRequest;
additional_bindings 可以让同一个 RPC 方法绑定多个 HTTP endpoint(GET/POST/PUT等)。
需要注意的是,如果希望通过 gRPC 服务自动生成 REST 接口,可以使用 Google 官方的 grpc-gateway 插件 protoc-gen-grpc-gateway,它会在 gRPC 服务前增加一层 HTTP 转发网关,将 HTTP 请求映射并转发到 gRPC 服务端。
相比之下,grpc-gateway 适合已有 gRPC 服务、希望兼容 REST 访问的场景;而 protoc-gen-go-http 则更偏向在 Kratos 中统一生成原生 gRPC + HTTP 服务代码,部署更轻量。
关于 grpc-gateway 的使用,我们在之前的文章「Golang 语言 gRPC 服务怎么同时支持 gRPC 和 HTTP 客户端调用?」中介绍过,本文不再赘述。
03 、在 Kratos 中使用 protoc-gen-go-http 插件
protoc-gen-go-http 插件是 Kratos 的一部分,它是 Kratos 官方开发和维护的,让我们可以通过 Protobuf IDL 同时生成 gRPC 服务和原生 HTTP 服务(基于 net/http),无需使用额外的 “网关”。
该插件的作用是根据 .proto 文件中的 google.api.http option,生成相应的 HTTP 适配层代码。具体来说,它会生成:
RegisterXXXHTTPServer(mux, server) 函数(用于把 gRPC 风格的服务注册为 HTTP handler)。XXXHTTPServer,定义 HTTP 层方法签名。google.api.http 选项里的路径映射)。这些代码都是纯 Go 的,在生成的代码文件 api/helloworld/v1/greeter_http.pb.go 中,不依赖 grpc-gateway 或任何中间层。
理论讲完了,接下来我们进入实战环节:如何用 protoc-gen-go-http 生成可直接运行的 HTTP 服务代码。
安装插件:
在使用 protoc-gen-go-http 插件之前,我们先通过命令安装插件:
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest
生成代码:
在 Part 02 中,我们定义的 .proto 文件,可以使用 protoc,或者 make 命令,或者 Kratos 提供的 CLI 工具 kratos,生成 Client 和 Service 代码。
我们以 kratos cli 为例,代码如下:
生成 Client 代码:
kratos proto client api/helloworld/v1/greeter.proto
生成代码文件:
api/helloworld/v1/greeter.pb.go
api/helloworld/v1/greeter_grpc.pb.go
# 注意 http 代码只会在 proto 文件中声明了 http 时才会生成
api/helloworld/v1/greeter_http.pb.go
其中,api/helloworld/v1/greeter_http.pb.go 文件就是提供 REST API 的相关代码。
// ...
type GreeterHTTPServer interface {
// SayHello Sends a greeting
SayHello(context.Context, *HelloRequest) (*HelloReply, error)
}
func RegisterGreeterHTTPServer(s *http.Server, srv GreeterHTTPServer) {
r := s.Route("/")
r.POST("/v1/greeter/say_hello", _Greeter_SayHello0_HTTP_Handler(srv))
r.GET("/helloworld/{name}", _Greeter_SayHello1_HTTP_Handler(srv))
}
// ...
protoc-gen-go-http 是 Kratos 在 gRPC 生态上的一次重要增强。
它让开发者可以在一份 .proto 文件中同时定义 gRPC 与 HTTP 接口,并自动生成服务代码,避免维护多套路由逻辑。
对于希望使用 Kratos 构建同时支持 gRPC + REST 的 Go 服务,这个插件几乎是“必备工具”。