/proc/self/cwd/source/common/grpc/common.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <cstdint> |
4 | | #include <string> |
5 | | |
6 | | #include "envoy/common/exception.h" |
7 | | #include "envoy/common/platform.h" |
8 | | #include "envoy/grpc/status.h" |
9 | | #include "envoy/http/filter.h" |
10 | | #include "envoy/http/header_map.h" |
11 | | #include "envoy/http/message.h" |
12 | | |
13 | | #include "source/common/common/hash.h" |
14 | | #include "source/common/grpc/status.h" |
15 | | #include "source/common/protobuf/protobuf.h" |
16 | | |
17 | | #include "absl/types/optional.h" |
18 | | #include "google/rpc/status.pb.h" |
19 | | |
20 | | namespace Envoy { |
21 | | namespace Grpc { |
22 | | |
23 | | class Exception : public EnvoyException { |
24 | | public: |
25 | | Exception(const absl::optional<uint64_t>& grpc_status, const std::string& message) |
26 | 0 | : EnvoyException(message), grpc_status_(grpc_status) {} |
27 | | |
28 | | const absl::optional<uint64_t> grpc_status_; |
29 | | }; |
30 | | |
31 | | class Common { |
32 | | public: |
33 | | /** |
34 | | * @param headers the headers to parse. |
35 | | * @return bool indicating whether content-type is gRPC. |
36 | | */ |
37 | | static bool hasGrpcContentType(const Http::RequestOrResponseHeaderMap& headers); |
38 | | |
39 | | /** |
40 | | * @param headers the headers to parse. |
41 | | * @return bool indicating whether Connect-Protocol-Version is present. |
42 | | */ |
43 | | static bool hasConnectProtocolVersionHeader(const Http::RequestOrResponseHeaderMap& headers); |
44 | | |
45 | | /** |
46 | | * @param headers the headers to parse. |
47 | | * @return bool indicating whether content-type is connect streaming. |
48 | | */ |
49 | | static bool hasConnectStreamingContentType(const Http::RequestOrResponseHeaderMap& headers); |
50 | | |
51 | | /** |
52 | | * @param headers the headers to parse. |
53 | | * @return bool indicating whether content-type is Protobuf. |
54 | | */ |
55 | | static bool hasProtobufContentType(const Http::RequestOrResponseHeaderMap& headers); |
56 | | |
57 | | /** |
58 | | * @param headers the headers to parse. |
59 | | * @return bool indicating whether the header is a gRPC request header. |
60 | | * Currently headers are considered gRPC request headers if they have the gRPC |
61 | | * content type, and have a path header. |
62 | | */ |
63 | | static bool isGrpcRequestHeaders(const Http::RequestHeaderMap& headers); |
64 | | |
65 | | /** |
66 | | * @param headers the headers to parse. |
67 | | * @return bool indicating whether the header is a Connect request header. |
68 | | * This is determined by checking for the connect protocol version header and a path header. |
69 | | */ |
70 | | static bool isConnectRequestHeaders(const Http::RequestHeaderMap& headers); |
71 | | |
72 | | /** |
73 | | * @param headers the headers to parse. |
74 | | * @return bool indicating whether the header is a Connect streaming request header. |
75 | | * This is determined by checking for the connect streaming content type and a path header. |
76 | | */ |
77 | | static bool isConnectStreamingRequestHeaders(const Http::RequestHeaderMap& headers); |
78 | | |
79 | | /** |
80 | | * @param headers the headers to parse. |
81 | | * @return bool indicating whether the header is a protobuf request header. |
82 | | * Currently headers are considered gRPC request headers if they have the protobuf |
83 | | * content type, and have a path header. |
84 | | */ |
85 | | static bool isProtobufRequestHeaders(const Http::RequestHeaderMap& headers); |
86 | | |
87 | | /** |
88 | | * @param headers the headers to parse. |
89 | | * @param bool indicating whether the header is at end_stream. |
90 | | * @return bool indicating whether the header is a gRPC response header |
91 | | */ |
92 | | static bool isGrpcResponseHeaders(const Http::ResponseHeaderMap& headers, bool end_stream); |
93 | | |
94 | | /** |
95 | | * @param headers the headers to parse. |
96 | | * @return bool indicating whether the header is a Connect streaming response header. |
97 | | */ |
98 | | static bool isConnectStreamingResponseHeaders(const Http::ResponseHeaderMap& headers); |
99 | | |
100 | | /** |
101 | | * Returns the GrpcStatus code from a given set of trailers, if present. |
102 | | * @param trailers the trailers to parse. |
103 | | * @param allow_user_status whether allow user defined grpc status. |
104 | | * if this value is false, custom grpc status is regarded as invalid status |
105 | | * @return absl::optional<Status::GrpcStatus> the parsed status code or InvalidCode if no valid |
106 | | * status is found. |
107 | | */ |
108 | | static absl::optional<Status::GrpcStatus> |
109 | | getGrpcStatus(const Http::ResponseHeaderOrTrailerMap& trailers, bool allow_user_defined = false); |
110 | | |
111 | | /** |
112 | | * Returns the GrpcStatus code from the set of trailers, headers, and StreamInfo, if present. |
113 | | * @param trailers the trailers to parse for a status code |
114 | | * @param headers the headers to parse if no status code was found in the trailers |
115 | | * @param info the StreamInfo to check for HTTP response code if no code was found in the trailers |
116 | | * or headers |
117 | | * @return absl::optional<Status::GrpcStatus> the parsed status code or absl::nullopt if no status |
118 | | * is found |
119 | | */ |
120 | | static absl::optional<Status::GrpcStatus> getGrpcStatus(const Http::ResponseTrailerMap& trailers, |
121 | | const Http::ResponseHeaderMap& headers, |
122 | | const StreamInfo::StreamInfo& info, |
123 | | bool allow_user_defined = false); |
124 | | |
125 | | /** |
126 | | * Returns the grpc-message from a given set of trailers, if present. |
127 | | * @param trailers the trailers to parse. |
128 | | * @return std::string the gRPC status message or empty string if grpc-message is not present in |
129 | | * trailers. |
130 | | */ |
131 | | static std::string getGrpcMessage(const Http::ResponseHeaderOrTrailerMap& trailers); |
132 | | |
133 | | /** |
134 | | * Returns the decoded google.rpc.Status message from a given set of trailers, if present. |
135 | | * @param trailers the trailers to parse. |
136 | | * @return std::unique_ptr<google::rpc::Status> the gRPC status message or empty pointer if no |
137 | | * grpc-status-details-bin trailer found or it was invalid. |
138 | | */ |
139 | | static absl::optional<google::rpc::Status> |
140 | | getGrpcStatusDetailsBin(const Http::HeaderMap& trailers); |
141 | | |
142 | | /** |
143 | | * Parse gRPC header 'grpc-timeout' value to a duration in milliseconds. |
144 | | * @param request_headers the header map from which to extract the value of 'grpc-timeout' header. |
145 | | * If this header is missing the timeout corresponds to infinity. The header is encoded in |
146 | | * maximum of 8 decimal digits and a char for the unit. |
147 | | * @return absl::optional<std::chrono::milliseconds> the duration in milliseconds. absl::nullopt |
148 | | * is returned if 'grpc-timeout' is missing or malformed. |
149 | | */ |
150 | | static absl::optional<std::chrono::milliseconds> |
151 | | getGrpcTimeout(const Http::RequestHeaderMap& request_headers); |
152 | | |
153 | | /** |
154 | | * Encode 'timeout' into 'grpc-timeout' format in the grpc-timeout header. |
155 | | * @param timeout the duration in std::chrono::milliseconds. |
156 | | * @param headers the HeaderMap in which the grpc-timeout header will be set with the timeout in |
157 | | * 'grpc-timeout' format, up to 8 decimal digits and a letter indicating the unit. |
158 | | */ |
159 | | static void toGrpcTimeout(const std::chrono::milliseconds& timeout, |
160 | | Http::RequestHeaderMap& headers); |
161 | | |
162 | | /** |
163 | | * Serialize protobuf message with gRPC frame header. |
164 | | */ |
165 | | static Buffer::InstancePtr serializeToGrpcFrame(const Protobuf::Message& message); |
166 | | |
167 | | /** |
168 | | * Serialize protobuf message. Without grpc header. |
169 | | */ |
170 | | static Buffer::InstancePtr serializeMessage(const Protobuf::Message& message); |
171 | | |
172 | | /** |
173 | | * Prepare headers for protobuf service. |
174 | | */ |
175 | | static Http::RequestMessagePtr |
176 | | prepareHeaders(const std::string& upstream_cluster, const std::string& service_full_name, |
177 | | const std::string& method_name, |
178 | | const absl::optional<std::chrono::milliseconds>& timeout); |
179 | | |
180 | | /** |
181 | | * @return const std::string& type URL prefix. |
182 | | */ |
183 | | static const std::string& typeUrlPrefix(); |
184 | | |
185 | | /** |
186 | | * Prefix type URL to a qualified name. |
187 | | * @param qualified_name packagename.messagename. |
188 | | * @return qualified_name prefixed with typeUrlPrefix + "/". |
189 | | */ |
190 | | static std::string typeUrl(const std::string& qualified_name); |
191 | | |
192 | | /** |
193 | | * Prepend a gRPC frame header to a Buffer::Instance containing a single gRPC frame. |
194 | | * @param buffer containing the frame data which will be modified. |
195 | | */ |
196 | | static void prependGrpcFrameHeader(Buffer::Instance& buffer); |
197 | | |
198 | | /** |
199 | | * Parse a Buffer::Instance into a Protobuf::Message. |
200 | | * @param buffer containing the data to be parsed. |
201 | | * @param proto the parsed proto. |
202 | | * @return bool true if the parse was successful. |
203 | | */ |
204 | | static bool parseBufferInstance(Buffer::InstancePtr&& buffer, Protobuf::Message& proto); |
205 | | |
206 | | struct RequestNames { |
207 | | absl::string_view service_; |
208 | | absl::string_view method_; |
209 | | }; |
210 | | |
211 | | /** |
212 | | * Resolve the gRPC service and method from the HTTP2 :path header. |
213 | | * @param path supplies the :path header. |
214 | | * @return if both gRPC serve and method have been resolved successfully returns |
215 | | * a populated RequestNames, otherwise returns an empty optional. |
216 | | * @note The return value is only valid as long as `path` is still valid and unmodified. |
217 | | */ |
218 | | static absl::optional<RequestNames> resolveServiceAndMethod(const Http::HeaderEntry* path); |
219 | | |
220 | | private: |
221 | | static constexpr size_t MAX_GRPC_TIMEOUT_VALUE = 99999999; |
222 | | }; |
223 | | |
224 | | } // namespace Grpc |
225 | | } // namespace Envoy |