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