grpc.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package mvc
  2. import (
  3. "net/http"
  4. "path"
  5. "github.com/kataras/iris/v12/context"
  6. )
  7. // GRPC registers a controller which serves gRPC clients.
  8. // It accepts the controller ptr to a struct value,
  9. // the gRPCServer itself, and a strict option which is explained below.
  10. //
  11. // The differences between an GRPC-based controller and a common one are:
  12. // HTTP verb: only POST (Party.AllowMethods can be used for more),
  13. // method parsing is disabled: path is the function name as it is,
  14. // if 'strictMode' option is true then this controller will only serve gRPC-based clients
  15. // and fires 404 on common HTTP clients,
  16. // otherwise HTTP clients can send and receive JSON (protos contain json struct fields by-default).
  17. type GRPC struct {
  18. // Server is required and should be gRPC Server derives from google's grpc package.
  19. Server http.Handler
  20. // ServiceName is required and should be the name of the service (used to build the gRPC route path),
  21. // e.g. "helloworld.Greeter".
  22. // For a controller's method of "SayHello" and ServiceName "helloworld.Greeter",
  23. // both gRPC and common HTTP request path is: "/helloworld.Greeter/SayHello".
  24. //
  25. // Tip: the ServiceName can be fetched through proto's file descriptor, e.g.
  26. // serviceName := pb.File_helloworld_proto.Services().Get(0).FullName().
  27. ServiceName string
  28. // When Strict option is true then this controller will only serve gRPC-based clients
  29. // and fires 404 on common HTTP clients.
  30. Strict bool
  31. }
  32. var _ Option = GRPC{}
  33. // Apply parses the controller's methods and registers gRPC handlers to the application.
  34. func (g GRPC) Apply(c *ControllerActivator) {
  35. defer c.Activated()
  36. pre := func(ctx *context.Context) {
  37. if ctx.IsGRPC() { // gRPC, consumes and produces protobuf.
  38. g.Server.ServeHTTP(ctx.ResponseWriter(), ctx.Request())
  39. ctx.StopExecution()
  40. return
  41. }
  42. // If strict was true fires 404 on common HTTP clients.
  43. if g.Strict {
  44. ctx.NotFound()
  45. ctx.StopExecution()
  46. return
  47. }
  48. // Allow common HTTP clients, consumes and produces JSON.
  49. ctx.Next()
  50. }
  51. for i := 0; i < c.Type.NumMethod(); i++ {
  52. m := c.Type.Method(i)
  53. path := path.Join(g.ServiceName, m.Name)
  54. if g.Strict {
  55. c.app.Router.HandleMany(http.MethodPost, path, pre)
  56. } else if route := c.Handle(http.MethodPost, path, m.Name, pre); route != nil {
  57. bckp := route.Description
  58. route.Description = "gRPC"
  59. if g.Strict {
  60. route.Description += "-only"
  61. }
  62. route.Description += " " + bckp // e.g. "gRPC controller"
  63. }
  64. }
  65. }