| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- package handler
- import (
- "fmt"
- "git.ikuban.com/server/kratos-utils/v2/http/middleware"
- ku_annotations "git.ikuban.com/server/kubanapis/kuban/api/annotations"
- "github.com/go-kratos/kratos/v2/transport/http"
- openapi_v3 "github.com/google/gnostic/openapiv3"
- "github.com/jhump/protoreflect/desc"
- "github.com/jhump/protoreflect/grpcreflect"
- "google.golang.org/genproto/googleapis/api/annotations"
- "google.golang.org/grpc"
- "google.golang.org/protobuf/proto"
- )
- func RegisterRoute(s *http.Server, srv any, svcDesc grpc.ServiceDesc) {
- r := s.Route("/api/")
- // 加载完整的服务描述符
- fullSvcDesc, err := grpcreflect.LoadServiceDescriptor(&svcDesc)
- if err != nil {
- panic(fmt.Sprintf("加载服务描述符失败 err:%v", err))
- }
- // 注册一元方法handler
- for _, md := range svcDesc.Methods {
- // 获取方法option
- option := GetOptionByServiceDescriptor(fullSvcDesc, svcDesc.ServiceName, md.MethodName)
- // 跳过不需要生成http方法的
- if !option.GenHttp {
- continue
- }
- // 注册http接口
- r.POST(option.Path, unaryHandler(srv, md, option))
- }
- // 注册流式方法handler
- for _, std := range svcDesc.Streams {
- // 获取方法option
- option := GetOptionByServiceDescriptor(fullSvcDesc, svcDesc.ServiceName, std.StreamName)
- // 跳过不需要生成http方法的
- if !option.GenHttp {
- continue
- }
- switch {
- case std.ClientStreams && std.ServerStreams:
- // 双向流
- case std.ClientStreams && !std.ServerStreams:
- // 客户端流
- case !std.ClientStreams && std.ServerStreams:
- // 服务端流
- r.POST(option.Path, serverStreamHandler(srv, std, option))
- }
- }
- }
- func GetOptionByServiceDescriptor(sd *desc.ServiceDescriptor, serviceName, methodName string) *middleware.Option {
- // 获取方法描述符
- md := sd.FindMethodByName(methodName)
- if md == nil {
- panic(fmt.Sprintf("未找到方法描述符 service:%v, method:%v", serviceName, methodName))
- }
- // option
- option := &middleware.Option{}
- // 获取方法option
- methodOptions := md.GetMethodOptions()
- operation := proto.GetExtension(methodOptions, openapi_v3.E_Operation).(*openapi_v3.Operation)
- if operation == nil {
- // 跳过不需要生成http方法的
- option.GenHttp = false
- return option
- }
- option.GenHttp = true
- // 不需要认证的
- if len(operation.Security) == 0 {
- option.NotAuth = true
- }
- // 解析自定义option [操作记录]
- customOptions := proto.GetExtension(methodOptions, ku_annotations.E_Options).(*ku_annotations.Options)
- if customOptions.GetOperationRecord().GetEnabled() {
- option.OperationRecord = true
- }
- // 路由
- rule := proto.GetExtension(methodOptions, annotations.E_Http).(*annotations.HttpRule)
- if rule != nil {
- switch httpRule := rule.GetPattern().(type) {
- case *annotations.HttpRule_Post:
- option.Path = httpRule.Post
- }
- }
- if option.Path == "" {
- option.Path = fmt.Sprintf("/%s/%s", serviceName, methodName)
- }
- return option
- }
|