Coverage Report

Created: 2023-11-12 09:30

/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