grpc.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package mvc
  2. import (
  3. "net/http"
  4. "path"
  5. "github.com/kataras/iris/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 by a common controller 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 g.Strict {
  43. ctx.NotFound()
  44. } else {
  45. // Allow common HTTP clients, consumes and produces JSON.
  46. ctx.Next()
  47. }
  48. }
  49. for i := 0; i < c.Type.NumMethod(); i++ {
  50. m := c.Type.Method(i)
  51. path := path.Join(g.ServiceName, m.Name)
  52. if route := c.Handle(http.MethodPost, path, m.Name, pre); route != nil {
  53. bckp := route.Description
  54. route.Description = "gRPC"
  55. if g.Strict {
  56. route.Description += "-only"
  57. }
  58. route.Description += " " + bckp // e.g. "gRPC controller"
  59. }
  60. }
  61. }