ClientInterceptors.swift 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 NIOCore
  17. /// A base class for client interceptors.
  18. ///
  19. /// Interceptors allow request and response parts to be observed, mutated or dropped as necessary.
  20. /// The default behaviour for this base class is to forward any events to the next interceptor.
  21. ///
  22. /// Interceptors may observe a number of different events:
  23. /// - receiving response parts with ``receive(_:context:)-5v1ih``,
  24. /// - receiving errors with ``errorCaught(_:context:)-6pncp``,
  25. /// - sending request parts with ``send(_:promise:context:)-4igtj``, and
  26. /// - RPC cancellation with ``cancel(promise:context:)-5tkf5``.
  27. ///
  28. /// These events flow through a pipeline of interceptors for each RPC. Request parts sent from the
  29. /// call object (e.g. ``UnaryCall``, ``BidirectionalStreamingCall``) will traverse the pipeline in the
  30. /// outbound direction from its tail via ``send(_:promise:context:)-4igtj`` eventually reaching the head of the
  31. /// pipeline where it will be sent sent to the server.
  32. ///
  33. /// Response parts, or errors, received from the transport fill be fired in the inbound direction
  34. /// back through the interceptor pipeline via ``receive(_:context:)-5v1ih`` and ``errorCaught(_:context:)-6pncp``,
  35. /// respectively. Note that the `end` response part and any error received are terminal: the
  36. /// pipeline will be torn down once these parts reach the the tail and are a signal that the
  37. /// interceptor should free up any resources it may be using.
  38. ///
  39. /// Each of the interceptor functions is provided with a `context` which exposes analogous functions
  40. /// (``receive(_:context:)-5v1ih``, ``errorCaught(_:context:)-6pncp``, ``send(_:promise:context:)-4igtj``, and ``cancel(promise:context:)-5tkf5``) which may be
  41. /// called to forward events to the next interceptor in the appropriate direction.
  42. ///
  43. /// ### Thread Safety
  44. ///
  45. /// Functions on `context` are not thread safe and **must** be called on the `EventLoop` found on
  46. /// the `context`. Since each interceptor is invoked on the same `EventLoop` this does not usually
  47. /// require any extra attention. However, if work is done on a `DispatchQueue` or _other_
  48. /// `EventLoop` then implementers should ensure that they use `context` from the correct
  49. /// `EventLoop`.
  50. #if swift(>=5.6)
  51. @preconcurrency open class ClientInterceptor<Request, Response>: @unchecked Sendable {
  52. public init() {}
  53. /// Called when the interceptor has received a response part to handle.
  54. /// - Parameters:
  55. /// - part: The response part which has been received from the server.
  56. /// - context: An interceptor context which may be used to forward the response part.
  57. open func receive(
  58. _ part: GRPCClientResponsePart<Response>,
  59. context: ClientInterceptorContext<Request, Response>
  60. ) {
  61. context.receive(part)
  62. }
  63. /// Called when the interceptor has received an error.
  64. /// - Parameters:
  65. /// - error: The error.
  66. /// - context: An interceptor context which may be used to forward the error.
  67. open func errorCaught(
  68. _ error: Error,
  69. context: ClientInterceptorContext<Request, Response>
  70. ) {
  71. context.errorCaught(error)
  72. }
  73. /// Called when the interceptor has received a request part to handle.
  74. /// - Parameters:
  75. /// - part: The request part which should be sent to the server.
  76. /// - promise: A promise which should be completed when the response part has been handled.
  77. /// - context: An interceptor context which may be used to forward the request part.
  78. open func send(
  79. _ part: GRPCClientRequestPart<Request>,
  80. promise: EventLoopPromise<Void>?,
  81. context: ClientInterceptorContext<Request, Response>
  82. ) {
  83. context.send(part, promise: promise)
  84. }
  85. /// Called when the interceptor has received a request to cancel the RPC.
  86. /// - Parameters:
  87. /// - promise: A promise which should be cancellation request has been handled.
  88. /// - context: An interceptor context which may be used to forward the cancellation request.
  89. open func cancel(
  90. promise: EventLoopPromise<Void>?,
  91. context: ClientInterceptorContext<Request, Response>
  92. ) {
  93. context.cancel(promise: promise)
  94. }
  95. }
  96. #else
  97. open class ClientInterceptor<Request, Response> {
  98. public init() {}
  99. /// Called when the interceptor has received a response part to handle.
  100. /// - Parameters:
  101. /// - part: The response part which has been received from the server.
  102. /// - context: An interceptor context which may be used to forward the response part.
  103. open func receive(
  104. _ part: GRPCClientResponsePart<Response>,
  105. context: ClientInterceptorContext<Request, Response>
  106. ) {
  107. context.receive(part)
  108. }
  109. /// Called when the interceptor has received an error.
  110. /// - Parameters:
  111. /// - error: The error.
  112. /// - context: An interceptor context which may be used to forward the error.
  113. open func errorCaught(
  114. _ error: Error,
  115. context: ClientInterceptorContext<Request, Response>
  116. ) {
  117. context.errorCaught(error)
  118. }
  119. /// Called when the interceptor has received a request part to handle.
  120. /// - Parameters:
  121. /// - part: The request part which should be sent to the server.
  122. /// - promise: A promise which should be completed when the response part has been handled.
  123. /// - context: An interceptor context which may be used to forward the request part.
  124. open func send(
  125. _ part: GRPCClientRequestPart<Request>,
  126. promise: EventLoopPromise<Void>?,
  127. context: ClientInterceptorContext<Request, Response>
  128. ) {
  129. context.send(part, promise: promise)
  130. }
  131. /// Called when the interceptor has received a request to cancel the RPC.
  132. /// - Parameters:
  133. /// - promise: A promise which should be cancellation request has been handled.
  134. /// - context: An interceptor context which may be used to forward the cancellation request.
  135. open func cancel(
  136. promise: EventLoopPromise<Void>?,
  137. context: ClientInterceptorContext<Request, Response>
  138. ) {
  139. context.cancel(promise: promise)
  140. }
  141. }
  142. #endif // swift(>=5.6)