gateway 项目实战
大约 2 分钟
1. 简介
gateway 项目包含以下技术栈:
- cobra: 提供命令行框架
 - zrpc: 基于 go-zero zrpc 框架提供 rpc 服务
 - gateway: 基于 go-zero gateway 框架, 支持以 http 方式调用 rpc 服务
 
2. 新建项目
jzero new simplegateway --frame gateway
cd simplegateway
go mod tidy3. 生成 swagger
jzero gen swagger4. 测试
go run main.go server
# 访问 localhost:8001/swagger 进行测试
至此, 你已经拥有了一个可用的 gateway 服务.
5. 开发教程
5.1. 鉴权
在实际的项目中, 鉴权是必不可少的, 那么在 jzero 的 gateway 模板中, 如何进行鉴权呢?
gateway 模板内置了中间件 header_processor
位置在 internal/middlewares/header_processor.go
内容如下:
package middleware
import (
	"context"
	"net/http"
	"github.com/zeromicro/go-zero/gateway"
	"google.golang.org/grpc"
)
func WithHeaderProcessor() gateway.Option {
	return gateway.WithHeaderProcessor(func(header http.Header) []string {
		var headers []string
		//// You can add header from request header here
		//// for example
		//for k, v := range header {
		//	if k == "Authorization" {
		//		headers = append(headers, fmt.Sprintf("%s:%s", k, strings.Join(v, ";")))
		//	}
		//}
		return headers
	})
}
func WithUnaryInterceptorValue(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
	//md, b := metadata.FromIncomingContext(ctx)
	//if !b {
	//	return handler(ctx, req)
	//}
	//// You can verify Authorization here and set user info in context value
	//// get Authorization
	//value := md.Get("Authorization")
	//if len(value) == 1 {
	//	// set context value
	//	ctx = context.WithValue(ctx, "Authorization", value[0])
	//}
	return handler(ctx, req)
}在 WithHeaderProcessor 中, 可将前端传来的 Authorization header 放入 grpc 的 metadata 中. 修改为如下:
func WithHeaderProcessor() gateway.Option {
	return gateway.WithHeaderProcessor(func(header http.Header) []string {
		var headers []string
		// You can add header from request header here
		// for example
		for k, v := range header {
			if k == "Authorization" {
				headers = append(headers, fmt.Sprintf("%s:%s", k, strings.Join(v, ";")))
			}
		}
		return headers
	})
}在 grpc 拦截器中获取 Authorization 值, 并校验获取出用户信息, 并设置到 context value 中.
func WithUnaryInterceptorValue(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
	md, b := metadata.FromIncomingContext(ctx)
	if !b {
		return handler(ctx, req)
	}
	// You can verify Authorization here and set user info in context value
	// get Authorization
	value := md.Get("Authorization")
	if len(value) == 1 {
		// set context value
		ctx = context.WithValue(ctx, "User", "jzero")
	}
	return handler(ctx, req)
}在 internal/middleware.go 中, 添加该拦截器
func RegisterZrpc(z *zrpc.RpcServer) {
	z.AddUnaryInterceptors(ServerValidationUnaryInterceptor)
	z.AddUnaryInterceptors(WithUnaryInterceptorValue)
}后续在 logic 获取用户信息如下:
func (l *SayHello) SayHello(in *hellopb.SayHelloRequest) (*hellopb.SayHelloResponse, error) {
	user := l.ctx.Value("User")
	
	return &hellopb.SayHelloResponse{
		Message: fmt.Sprintf("Hello, %s", user),
	}, nil
}5.2 middleware 分组控制
please see: middleware 分组控制
