| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- 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, baseUrl string) {
- r := s.Route("/api/")
- if baseUrl != "" {
- r = s.Route(baseUrl)
- }
- // 加载完整的服务描述符
- 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
- }
- // 解析自定义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 = fmt.Sprintf("/%s/%s", serviceName, methodName)
- }
- if option.Method == "" {
- option.Method = http2.MethodPost
- }
- return option
- }
|