package handler import ( "fmt" http2 "net/http" "git.ikuban.com/server/kratos-utils/v2/transport/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("/") // 加载完整的服务描述符 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.Handle(option.Method, 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 } else { if len(operation.Security[0].AdditionalProperties) != 0 { option.AuthorizationsName = operation.Security[0].AdditionalProperties[0].Name } } // 解析自定义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 option.Method = http2.MethodPost case *annotations.HttpRule_Get: option.Path = httpRule.Get option.Method = http2.MethodGet case *annotations.HttpRule_Delete: option.Path = httpRule.Delete option.Method = http2.MethodDelete case *annotations.HttpRule_Put: option.Path = httpRule.Put option.Method = http2.MethodPut } } if option.Path == "" { option.Path = pathGenerator(serviceName, methodName) } if option.Method == "" { option.Method = http2.MethodPost } return option }