2
0

Interceptors.swift 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. @unchecked Sendable
  24. {
  25. /// Called when the interceptor has received a request part to handle.
  26. ///
  27. /// - Parameters:
  28. /// - part: The request part to send to the server.
  29. /// - promise: A promise to complete once the request part has been written to the network.
  30. /// - context: An interceptor context which may be used to forward the request part to the next
  31. /// interceptor.
  32. override func send(
  33. _ part: GRPCClientRequestPart<Echo_EchoRequest>,
  34. promise: EventLoopPromise<Void>?,
  35. context: ClientInterceptorContext<Echo_EchoRequest, Echo_EchoResponse>
  36. ) {
  37. switch part {
  38. // The (user-provided) request headers, we send these at the start of each RPC. They will be
  39. // augmented with transport specific headers once the request part reaches the transport.
  40. case let .metadata(headers):
  41. print("> Starting '\(context.path)' RPC, headers:", prettify(headers))
  42. // The request message and metadata (ignored here). For unary and server-streaming RPCs we
  43. // expect exactly one message, for client-streaming and bidirectional streaming RPCs any number
  44. // of messages is permitted.
  45. case let .message(request, _):
  46. print("> Sending request with text '\(request.text)'")
  47. // The end of the request stream: must be sent exactly once, after which no more messages may
  48. // be sent.
  49. case .end:
  50. print("> Closing request stream")
  51. }
  52. // Forward the request part to the next interceptor.
  53. context.send(part, promise: promise)
  54. }
  55. /// Called when the interceptor has received a response part to handle.
  56. ///
  57. /// - Parameters:
  58. /// - part: The response part received from the server.
  59. /// - context: An interceptor context which may be used to forward the response part to the next
  60. /// interceptor.
  61. override func receive(
  62. _ part: GRPCClientResponsePart<Echo_EchoResponse>,
  63. context: ClientInterceptorContext<Echo_EchoRequest, Echo_EchoResponse>
  64. ) {
  65. switch part {
  66. // The response headers received from the server. We expect to receive these once at the start
  67. // of a response stream, however, it is also valid to see no 'metadata' parts on the response
  68. // stream if the server rejects the RPC (in which case we expect the 'end' part).
  69. case let .metadata(headers):
  70. print("< Received headers:", prettify(headers))
  71. // A response message received from the server. For unary and client-streaming RPCs we expect
  72. // one message. For server-streaming and bidirectional-streaming we expect any number of
  73. // messages (including zero).
  74. case let .message(response):
  75. print("< Received response with text '\(response.text)'")
  76. // The end of the response stream (and by extension, request stream). We expect one 'end' part,
  77. // after which no more response parts may be received and no more request parts will be sent.
  78. case let .end(status, trailers):
  79. print("< Response stream closed with status: '\(status)' and trailers:", prettify(trailers))
  80. }
  81. // Forward the response part to the next interceptor.
  82. context.receive(part)
  83. }
  84. }
  85. /// This class is an implementation of a *generated* protocol for the client which has one factory
  86. /// method per RPC returning the interceptors to use. The relevant factory method is call when
  87. /// invoking each RPC. An implementation of this protocol can be set on the generated client.
  88. public final class ExampleClientInterceptorFactory: Echo_EchoClientInterceptorFactoryProtocol {
  89. public init() {}
  90. // Returns an array of interceptors to use for the 'Get' RPC.
  91. public func makeGetInterceptors() -> [ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse>] {
  92. return [LoggingEchoClientInterceptor()]
  93. }
  94. // Returns an array of interceptors to use for the 'Expand' RPC.
  95. public func makeExpandInterceptors() -> [ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse>] {
  96. return [LoggingEchoClientInterceptor()]
  97. }
  98. // Returns an array of interceptors to use for the 'Collect' RPC.
  99. public func makeCollectInterceptors()
  100. -> [ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse>]
  101. {
  102. return [LoggingEchoClientInterceptor()]
  103. }
  104. // Returns an array of interceptors to use for the 'Update' RPC.
  105. public func makeUpdateInterceptors() -> [ClientInterceptor<Echo_EchoRequest, Echo_EchoResponse>] {
  106. return [LoggingEchoClientInterceptor()]
  107. }
  108. }