route.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package handler
  2. import (
  3. "fmt"
  4. http2 "net/http"
  5. "git.ikuban.com/server/kratos-utils/v2/transport/middleware"
  6. ku_annotations "git.ikuban.com/server/kubanapis/kuban/api/annotations"
  7. "github.com/go-kratos/kratos/v2/transport/http"
  8. openapi_v3 "github.com/google/gnostic/openapiv3"
  9. "github.com/jhump/protoreflect/desc"
  10. "github.com/jhump/protoreflect/grpcreflect"
  11. "google.golang.org/genproto/googleapis/api/annotations"
  12. "google.golang.org/grpc"
  13. "google.golang.org/protobuf/proto"
  14. )
  15. func RegisterRoute(s *http.Server, srv any, svcDesc grpc.ServiceDesc) {
  16. r := s.Route("/")
  17. // 加载完整的服务描述符
  18. fullSvcDesc, err := grpcreflect.LoadServiceDescriptor(&svcDesc)
  19. if err != nil {
  20. panic(fmt.Sprintf("加载服务描述符失败 err:%v", err))
  21. }
  22. // 注册一元方法handler
  23. for _, md := range svcDesc.Methods {
  24. // 获取方法option
  25. option := GetOptionByServiceDescriptor(fullSvcDesc, svcDesc.ServiceName, md.MethodName)
  26. // 跳过不需要生成http方法的
  27. if !option.GenHttp {
  28. continue
  29. }
  30. // 注册http接口
  31. r.Handle(option.Method, option.Path, unaryHandler(srv, md, option))
  32. }
  33. // 注册流式方法handler
  34. for _, std := range svcDesc.Streams {
  35. // 获取方法option
  36. option := GetOptionByServiceDescriptor(fullSvcDesc, svcDesc.ServiceName, std.StreamName)
  37. // 跳过不需要生成http方法的
  38. if !option.GenHttp {
  39. continue
  40. }
  41. switch {
  42. case std.ClientStreams && std.ServerStreams:
  43. // 双向流
  44. case std.ClientStreams && !std.ServerStreams:
  45. // 客户端流
  46. case !std.ClientStreams && std.ServerStreams:
  47. // 服务端流
  48. r.POST(option.Path, serverStreamHandler(srv, std, option))
  49. }
  50. }
  51. }
  52. func GetOptionByServiceDescriptor(sd *desc.ServiceDescriptor, serviceName, methodName string) *middleware.Option {
  53. // 获取方法描述符
  54. md := sd.FindMethodByName(methodName)
  55. if md == nil {
  56. panic(fmt.Sprintf("未找到方法描述符 service:%v, method:%v", serviceName, methodName))
  57. }
  58. // option
  59. option := &middleware.Option{}
  60. // 获取方法option
  61. methodOptions := md.GetMethodOptions()
  62. operation := proto.GetExtension(methodOptions, openapi_v3.E_Operation).(*openapi_v3.Operation)
  63. if operation == nil {
  64. // 跳过不需要生成http方法的
  65. option.GenHttp = false
  66. return option
  67. }
  68. option.GenHttp = true
  69. // 不需要认证的
  70. if len(operation.Security) == 0 {
  71. option.NotAuth = true
  72. } else {
  73. if len(operation.Security[0].AdditionalProperties) != 0 {
  74. option.AuthorizationsName = operation.Security[0].AdditionalProperties[0].Name
  75. }
  76. }
  77. // 解析自定义option [操作记录]
  78. customOptions := proto.GetExtension(methodOptions, ku_annotations.E_Options).(*ku_annotations.Options)
  79. if customOptions.GetOperationRecord().GetEnabled() {
  80. option.OperationRecord = true
  81. }
  82. // 路由
  83. rule := proto.GetExtension(methodOptions, annotations.E_Http).(*annotations.HttpRule)
  84. if rule != nil {
  85. switch httpRule := rule.GetPattern().(type) {
  86. case *annotations.HttpRule_Post:
  87. option.Path = httpRule.Post
  88. option.Method = http2.MethodPost
  89. case *annotations.HttpRule_Get:
  90. option.Path = httpRule.Get
  91. option.Method = http2.MethodGet
  92. case *annotations.HttpRule_Delete:
  93. option.Path = httpRule.Delete
  94. option.Method = http2.MethodDelete
  95. case *annotations.HttpRule_Put:
  96. option.Path = httpRule.Put
  97. option.Method = http2.MethodPut
  98. }
  99. }
  100. if option.Path == "" {
  101. option.Path = pathGenerator(serviceName, methodName)
  102. }
  103. if option.Method == "" {
  104. option.Method = http2.MethodPost
  105. }
  106. return option
  107. }