/src/grpc-swift/Sources/GRPC/ServerErrorProcessor.swift
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2021, 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 NIOHPACK |
17 | | |
18 | | @usableFromInline |
19 | | internal enum ServerErrorProcessor { |
20 | | /// Processes a library error to form a `GRPCStatus` and trailers to send back to the client. |
21 | | /// - Parameter error: The error to process. |
22 | | /// - Returns: The status and trailers to send to the client. |
23 | | @usableFromInline |
24 | | internal static func processLibraryError( |
25 | | _ error: Error, |
26 | | delegate: ServerErrorDelegate? |
27 | 72.3k | ) -> (GRPCStatus, HPACKHeaders) { |
28 | 72.3k | // Observe the error if we have a delegate. |
29 | 72.3k | delegate?.observeLibraryError(error) |
30 | 72.3k | |
31 | 72.3k | // What status are we terminating this RPC with? |
32 | 72.3k | // - If we have a delegate, try transforming the error. If the delegate returns trailers, merge |
33 | 72.3k | // them with any on the call context. |
34 | 72.3k | // - If we don't have a delegate, then try to transform the error to a status. |
35 | 72.3k | // - Fallback to a generic error. |
36 | 72.3k | let status: GRPCStatus |
37 | 72.3k | let trailers: HPACKHeaders |
38 | 72.3k | |
39 | 72.3k | if let transformed = delegate?.transformLibraryError(error) { |
40 | 0 | status = transformed.status |
41 | 0 | trailers = transformed.trailers ?? [:] |
42 | 23.1k | } else if let grpcStatusTransformable = error as? GRPCStatusTransformable { |
43 | 23.1k | status = grpcStatusTransformable.makeGRPCStatus() |
44 | 23.1k | trailers = [:] |
45 | 49.1k | } else { |
46 | 49.1k | // Eh... well, we don't know what status to use. Use a generic one. |
47 | 49.1k | status = .processingError(cause: error) |
48 | 49.1k | trailers = [:] |
49 | 49.1k | } |
50 | 72.3k | |
51 | 72.3k | return (status, trailers) |
52 | 72.3k | } |
53 | | |
54 | | /// Processes an error, transforming it into a 'GRPCStatus' and any trailers to send to the peer. |
55 | | @usableFromInline |
56 | | internal static func processObserverError( |
57 | | _ error: Error, |
58 | | headers: HPACKHeaders, |
59 | | trailers: HPACKHeaders, |
60 | | delegate: ServerErrorDelegate? |
61 | 0 | ) -> (GRPCStatus, HPACKHeaders) { |
62 | 0 | // Observe the error if we have a delegate. |
63 | 0 | delegate?.observeRequestHandlerError(error, headers: headers) |
64 | 0 |
|
65 | 0 | // What status are we terminating this RPC with? |
66 | 0 | // - If we have a delegate, try transforming the error. If the delegate returns trailers, merge |
67 | 0 | // them with any on the call context. |
68 | 0 | // - If we don't have a delegate, then try to transform the error to a status. |
69 | 0 | // - Fallback to a generic error. |
70 | 0 | let status: GRPCStatus |
71 | 0 | let mergedTrailers: HPACKHeaders |
72 | 0 |
|
73 | 0 | if let transformed = delegate?.transformRequestHandlerError(error, headers: headers) { |
74 | 0 | status = transformed.status |
75 | 0 | if var transformedTrailers = transformed.trailers { |
76 | 0 | // The delegate returned trailers: merge in those from the context as well. |
77 | 0 | transformedTrailers.add(contentsOf: trailers) |
78 | 0 | mergedTrailers = transformedTrailers |
79 | 0 | } else { |
80 | 0 | mergedTrailers = trailers |
81 | 0 | } |
82 | 0 | } else if let grpcStatusTransformable = error as? GRPCStatusTransformable { |
83 | 0 | status = grpcStatusTransformable.makeGRPCStatus() |
84 | 0 | mergedTrailers = trailers |
85 | 0 | } else { |
86 | 0 | // Eh... well, we don't what status to use. Use a generic one. |
87 | 0 | status = .processingError(cause: error) |
88 | 0 | mergedTrailers = trailers |
89 | 0 | } |
90 | 0 |
|
91 | 0 | return (status, mergedTrailers) |
92 | 0 | } |
93 | | } |