You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 5.0 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. # Interceptor
  2. gRPC provides simple APIs to implement and install interceptors on a per
  3. ClientConn/Server basis. Interceptor intercepts the execution of each RPC call.
  4. Users can use interceptors to do logging, authentication/authorization, metrics
  5. collection, and many other functionality that can be shared across RPCs.
  6. ## Try it
  7. ```
  8. go run server/main.go
  9. ```
  10. ```
  11. go run client/main.go
  12. ```
  13. ## Explanation
  14. In gRPC, interceptors can be categorized into two kinds in terms of the type of
  15. RPC calls they intercept. The first one is the **unary interceptor**, which
  16. intercepts unary RPC calls. And the other is the **stream interceptor** which
  17. deals with streaming RPC calls. See
  18. [here](https://grpc.io/docs/guides/concepts.html#rpc-life-cycle) for explanation
  19. about unary RPCs and streaming RPCs. Each of client and server has their own
  20. types of unary and stream interceptors. Thus, there are in total four different
  21. types of interceptors in gRPC.
  22. ### Client-side
  23. #### Unary Interceptor
  24. [`UnaryClientInterceptor`](https://godoc.org/google.golang.org/grpc#UnaryClientInterceptor)
  25. is the type for client-side unary interceptor. It is essentially a function type
  26. with signature: `func(ctx context.Context, method string, req, reply
  27. interface{}, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error`.
  28. An implementation of a unary interceptor can usually be divided into three
  29. parts: pre-processing, invoking RPC method, and post-processing.
  30. For pre-processing, users can get info about the current RPC call by examining
  31. the args passed in, such as RPC context, method string, request to be sent, and
  32. CallOptions configured. With the info, users can even modify the RPC call. For
  33. instance, in the example, we examine the list of CallOptions and see if call
  34. credential has been configured. If not, configure it to use oauth2 with token
  35. "some-secrete-token" as fallback. In our example, we intentionally omit
  36. configuring the per RPC credential to resort to fallback.
  37. After pre-processing is done, use can invoke the RPC call by calling the
  38. `invoker`.
  39. Once the invoker returns the reply and error, user can do post-processing of the
  40. RPC call. Usually, it's about dealing with the returned reply and error. In the
  41. example, we log the RPC timing and error info.
  42. To install a unary interceptor on a ClientConn, configure `Dial` with
  43. `DialOption`
  44. [`WithUnaryInterceptor`](https://godoc.org/google.golang.org/grpc#WithUnaryInterceptor).
  45. #### Stream Interceptor
  46. [`StreamClientInterceptor`](https://godoc.org/google.golang.org/grpc#StreamClientInterceptor)
  47. is the type for client-side stream interceptor. It is a function type with
  48. signature: `func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method
  49. string, streamer Streamer, opts ...CallOption) (ClientStream, error)`. An
  50. implementation of a stream interceptor usually include pre-processing, and
  51. stream operation interception.
  52. For pre-processing, it's similar to unary interceptor.
  53. However, rather than doing the RPC method invocation and post-processing
  54. afterwards, stream interceptor intercepts the users' operation on the stream.
  55. First, the interceptor calls the passed-in `streamer` to get a `ClientStream`,
  56. and then wraps around the `ClientStream` and overloading its methods with
  57. intercepting logic. Finally, interceptors returns the wrapped `ClientStream` to
  58. user to operate on.
  59. In the example, we define a new struct `wrappedStream`, which is embedded with a
  60. `ClientStream`. Then, we implement (overload) the `SendMsg` and `RecvMsg`
  61. methods on `wrappedStream` to intercepts these two operations on the embedded
  62. `ClientStream`. In the example, we log the message type info and time info for
  63. interception purpose.
  64. To install the stream interceptor for a ClientConn, configure `Dial` with
  65. `DialOption`
  66. [`WithStreamInterceptor`](https://godoc.org/google.golang.org/grpc#WithStreamInterceptor).
  67. ### Server-side
  68. Server side interceptor is similar to client side, though with slightly
  69. different provided info.
  70. #### Unary Interceptor
  71. [`UnaryServerInterceptor`](https://godoc.org/google.golang.org/grpc#UnaryServerInterceptor)
  72. is the type for server-side unary interceptor. It is a function type with
  73. signature: `func(ctx context.Context, req interface{}, info *UnaryServerInfo,
  74. handler UnaryHandler) (resp interface{}, err error)`.
  75. Refer to client-side unary interceptor section for detailed implementation
  76. explanation.
  77. To install the unary interceptor for a Server, configure `NewServer` with
  78. `ServerOption`
  79. [`UnaryInterceptor`](https://godoc.org/google.golang.org/grpc#UnaryInterceptor).
  80. #### Stream Interceptor
  81. [`StreamServerInterceptor`](https://godoc.org/google.golang.org/grpc#StreamServerInterceptor)
  82. is the type for server-side stream interceptor. It is a function type with
  83. signature: `func(srv interface{}, ss ServerStream, info *StreamServerInfo,
  84. handler StreamHandler) error`.
  85. Refer to client-side stream interceptor section for detailed implementation
  86. explanation.
  87. To install the unary interceptor for a Server, configure `NewServer` with
  88. `ServerOption`
  89. [`StreamInterceptor`](https://godoc.org/google.golang.org/grpc#StreamInterceptor).