LCOV - code coverage report
Current view: top level - source/common/http - status.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 10 10 100.0 %
Date: 2024-01-05 06:35:25 Functions: 4 4 100.0 %

          Line data    Source code
       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      280089 : 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       66389 :   do {                                                                                             \
     139       66389 :     if (::Envoy::Http::Details::StatusAdapter adapter{(expr)}) {                                   \
     140       66262 :     } else {                                                                                       \
     141         127 :       return std::move(adapter.status_);                                                           \
     142         127 :     }                                                                                              \
     143       66389 :   } 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          56 :   StatusAdapter(const Status& status) : status_(status) {}
     149       66334 :   StatusAdapter(Status&& status) : status_(std::move(status)) {}
     150             : 
     151             :   StatusAdapter(const StatusAdapter&) = delete;
     152             :   StatusAdapter& operator=(const StatusAdapter&) = delete;
     153             : 
     154       66390 :   explicit operator bool() const { return status_.ok(); }
     155             : 
     156             :   Status status_;
     157             : };
     158             : } // namespace Details
     159             : 
     160             : } // namespace Http
     161             : } // namespace Envoy

Generated by: LCOV version 1.15