Interceptors.swift 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright 2020, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import EchoModel
  17. import GRPC
  18. import NIOCore
  19. // All client interceptors derive from the 'ClientInterceptor' base class. We know the request and
  20. // response types for all Echo RPCs are the same: so we'll use them concretely here, allowing us
  21. // to access fields on each type as we intercept them.
  22. class LoggingEchoClientInterceptor: ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse> {
  23. /// Called when the interceptor has received a request part to handle.
  24. ///
  25. /// - Parameters:
  26. /// - part: The request part to send to the server.
  27. /// - promise: A promise to complete once the request part has been written to the network.
  28. /// - context: An interceptor context which may be used to forward the request part to the next
  29. /// interceptor.
  30. override func send(
  31. _ part: GRPCClientRequestPart<Echo_EchoRequest>,
  32. promise: EventLoopPromise<Void>?,
  33. context: ClientInterceptorContext<Echo_EchoRequest, Echo_EchoResponse>
  34. ) {
  35. switch part {
  36. // The (user-provided) request headers, we send these at the start of each RPC. They will be
  37. // augmented with transport specific headers once the request part reaches the transport.
  38. case let .metadata(headers):
  39. print("> Starting '\(context.path)' RPC, headers:", prettify(headers))
  40. // The request message and metadata (ignored here). For unary and server-streaming RPCs we
  41. // expect exactly one message, for client-streaming and bidirectional streaming RPCs any number
  42. // of messages is permitted.
  43. case let .message(request, _):
  44. print("> Sending request with text '\(request.text)'")
  45. // The end of the request stream: must be sent exactly once, after which no more messages may
  46. // be sent.
  47. case .end:
  48. print("> Closing request stream")
  49. }
  50. // Forward the request part to the next interceptor.
  51. context.send(part, promise: promise)
  52. }
  53. /// Called when the interceptor has received a response part to handle.
  54. ///
  55. /// - Parameters:
  56. /// - part: The response part received from the server.
  57. /// - context: An interceptor context which may be used to forward the response part to the next
  58. /// interceptor.
  59. override func receive(
  60. _ part: GRPCClientResponsePart<Echo_EchoResponse>,
  61. context: ClientInterceptorContext<Echo_EchoRequest, Echo_EchoResponse>
  62. ) {
  63. switch part {
  64. // The response headers received from the server. We expect to receive these once at the start
  65. // of a response stream, however, it is also valid to see no 'metadata' parts on the response
  66. // stream if the server rejects the RPC (in which case we expect the 'end' part).
  67. case let .metadata(headers):
  68. print("< Received headers:", prettify(headers))
  69. // A response message received from the server. For unary and client-streaming RPCs we expect
  70. // one message. For server-streaming and bidirectional-streaming we expect any number of
  71. // messages (including zero).
  72. case let .message(response):
  73. print("< Received response with text '\(response.text)'")
  74. // The end of the response stream (and by extension, request stream). We expect one 'end' part,
  75. // after which no more response parts may be received and no more request parts will be sent.
  76. case let .end(status, trailers):
  77. print("< Response stream closed with status: '\(status)' and trailers:", prettify(trailers))
  78. }
  79. // Forward the response part to the next interceptor.
  80. context.receive(part)
  81. }
  82. }
  83. /// This class is an implementation of a *generated* protocol for the client which has one factory
  84. /// method per RPC returning the interceptors to use. The relevant factory method is call when
  85. /// invoking each RPC. An implementation of this protocol can be set on the generated client.
  86. public final class ExampleClientInterceptorFactory: Echo_EchoClientInterceptorFactoryProtocol {
  87. public init() {}
  88. // Returns an array of interceptors to use for the 'Get' RPC.
  89. public func makeGetInterceptors() -> [ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse>] {
  90. return [LoggingEchoClientInterceptor()]
  91. }
  92. // Returns an array of interceptors to use for the 'Expand' RPC.
  93. public func makeExpandInterceptors() -> [ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse>] {
  94. return [LoggingEchoClientInterceptor()]
  95. }
  96. // Returns an array of interceptors to use for the 'Collect' RPC.
  97. public func makeCollectInterceptors()
  98. -> [ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse>] {
  99. return [LoggingEchoClientInterceptor()]
  100. }
  101. // Returns an array of interceptors to use for the 'Update' RPC.
  102. public func makeUpdateInterceptors() -> [ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse>] {
  103. return [LoggingEchoClientInterceptor()]
  104. }
  105. }