/proc/self/cwd/source/common/http/status.h
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include <atomic> |
4 | | #include <string> |
5 | | |
6 | | #include "envoy/http/codes.h" |
7 | | |
8 | | #include "absl/status/status.h" |
9 | | #include "absl/strings/string_view.h" |
10 | | |
11 | | /** |
12 | | * Facility for returning rich error information. |
13 | | * This facility is to be used in place of exceptions, in components where |
14 | | * exceptions safety is not guaranteed (i.e. codecs). |
15 | | * |
16 | | * Envoy::Status is an alias of absl::Status. |
17 | | * IMPORTANT: `absl::Status` constructor `absl::Status::code()` and absl::Status::ToString()` |
18 | | * methods must not be used as they will not return correct error information. Instead the error |
19 | | * value creating and corresponding error checking functions defined below must be used. |
20 | | * TODO(yanavlasov): add clang-tidy or lint check to enforce this. |
21 | | * |
22 | | * Usage example: |
23 | | * |
24 | | * Envoy::Status Foo() { |
25 | | * ... |
26 | | * if (codec_error) { |
27 | | * return CodecProtocolError("Invalid protocol"); |
28 | | * } |
29 | | * return Envoy::OkStatus(); |
30 | | * } |
31 | | * |
32 | | * void Bar() { |
33 | | * auto status = Foo(); |
34 | | * if (status.ok()) { |
35 | | * ... |
36 | | * } else { |
37 | | * ASSERT(IsCodecProtocolError(status)); |
38 | | * ENVOY_LOG(debug, "Codec error encountered: {}", status.message()); |
39 | | * } |
40 | | * } |
41 | | */ |
42 | | |
43 | | namespace Envoy { |
44 | | namespace Http { |
45 | | |
46 | | /** |
47 | | * Status codes for representing classes of Envoy errors. |
48 | | */ |
49 | | enum class StatusCode : int { |
50 | | Ok = 0, |
51 | | |
52 | | /** |
53 | | * Indicates a non-recoverable protocol error that should result in connection termination. |
54 | | */ |
55 | | CodecProtocolError = 1, |
56 | | |
57 | | /** |
58 | | * Indicates detection of outbound frame queue flood. |
59 | | */ |
60 | | BufferFloodError = 2, |
61 | | |
62 | | /** |
63 | | * Indicates a response is received on a connection that did not send a request. In practice |
64 | | * this can only happen on HTTP/1.1 connections. |
65 | | */ |
66 | | PrematureResponseError = 3, |
67 | | |
68 | | /** |
69 | | * Indicates a client (local) side error which should not happen. |
70 | | */ |
71 | | CodecClientError = 4, |
72 | | |
73 | | /** |
74 | | * Indicates that peer sent too many consecutive DATA frames with empty payload. |
75 | | */ |
76 | | InboundFramesWithEmptyPayload = 5, |
77 | | |
78 | | /** |
79 | | * Indicates that Envoy is overloaded and may shed load. |
80 | | */ |
81 | | EnvoyOverloadError = 6, |
82 | | }; |
83 | | |
84 | | using Status = absl::Status; |
85 | | |
86 | 7.72M | inline Status okStatus() { return absl::OkStatus(); } |
87 | | |
88 | | /** |
89 | | * Returns the combination of the error code name, message and any additional error attributes. |
90 | | */ |
91 | | std::string toString(const Status& status); |
92 | | |
93 | | /** |
94 | | * Functions for creating error values. The error code of the returned status object matches the |
95 | | * name of the function. |
96 | | */ |
97 | | Status codecProtocolError(absl::string_view message); |
98 | | Status bufferFloodError(absl::string_view message); |
99 | | Status prematureResponseError(absl::string_view message, Http::Code http_code); |
100 | | Status codecClientError(absl::string_view message); |
101 | | Status inboundFramesWithEmptyPayloadError(); |
102 | | Status envoyOverloadError(absl::string_view message); |
103 | | |
104 | | /** |
105 | | * Returns Envoy::StatusCode of the given status object. |
106 | | * If the status object does not contain valid Envoy::Status value the function will ASSERT. |
107 | | */ |
108 | | StatusCode getStatusCode(const Status& status); |
109 | | |
110 | | /** |
111 | | * Returns true if the given status matches error code implied by the name of the function. |
112 | | */ |
113 | | ABSL_MUST_USE_RESULT bool isCodecProtocolError(const Status& status); |
114 | | ABSL_MUST_USE_RESULT bool isBufferFloodError(const Status& status); |
115 | | ABSL_MUST_USE_RESULT bool isPrematureResponseError(const Status& status); |
116 | | ABSL_MUST_USE_RESULT bool isCodecClientError(const Status& status); |
117 | | ABSL_MUST_USE_RESULT bool isInboundFramesWithEmptyPayloadError(const Status& status); |
118 | | ABSL_MUST_USE_RESULT bool isEnvoyOverloadError(const Status& status); |
119 | | |
120 | | /** |
121 | | * Returns Http::Code value of the PrematureResponseError status. |
122 | | * IsPrematureResponseError(status) must be true which is checked by ASSERT. |
123 | | */ |
124 | | Http::Code getPrematureResponseHttpCode(const Status& status); |
125 | | |
126 | | /** |
127 | | * Macro that checks return value of expression that results in Status and returns from |
128 | | * the current function is status is not OK. |
129 | | * |
130 | | * Example usage: |
131 | | * Status foo() { |
132 | | * RETURN_IF_ERROR(bar()); |
133 | | * return okStatus(); |
134 | | * } |
135 | | */ |
136 | | |
137 | | #define RETURN_IF_ERROR(expr) \ |
138 | 1.84M | do { \ |
139 | 1.84M | if (::Envoy::Http::Details::StatusAdapter adapter{(expr)}) { \ |
140 | 1.82M | } else { \ |
141 | 23.1k | return std::move(adapter.status_); \ |
142 | 23.1k | } \ |
143 | 1.84M | } while (false) |
144 | | |
145 | | namespace Details { |
146 | | // Helper class to convert `Status` to `bool` so it can be used inside `if` statements. |
147 | | struct StatusAdapter { |
148 | 5.11k | StatusAdapter(const Status& status) : status_(status) {} |
149 | 1.84M | StatusAdapter(Status&& status) : status_(std::move(status)) {} |
150 | | |
151 | | StatusAdapter(const StatusAdapter&) = delete; |
152 | | StatusAdapter& operator=(const StatusAdapter&) = delete; |
153 | | |
154 | 1.84M | explicit operator bool() const { return status_.ok(); } |
155 | | |
156 | | Status status_; |
157 | | }; |
158 | | } // namespace Details |
159 | | |
160 | | } // namespace Http |
161 | | } // namespace Envoy |