xref: /openbmc/bmcweb/redfish-core/include/utils/error_code.hpp (revision 5d92fffcbd59ade1fb0a24f65d0e15ce4e414927)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 #pragma once
4 
5 #include "error_message_utils.hpp"
6 #include "http_response.hpp"
7 
8 #include <algorithm>
9 #include <array>
10 #include <cstddef>
11 #include <limits>
12 
13 namespace redfish
14 {
15 // Propagates the worst error code to the final response.
16 // The order of error code is (from high to low)
17 // 500 Internal Server Error
18 // 511 Network Authentication Required
19 // 510 Not Extended
20 // 508 Loop Detected
21 // 507 Insufficient Storage
22 // 506 Variant Also Negotiates
23 // 505 HTTP Version Not Supported
24 // 504 Gateway Timeout
25 // 503 Service Unavailable
26 // 502 Bad Gateway
27 // 501 Not Implemented
28 // 401 Unauthorized
29 // 451 - 409 Error codes (not listed explicitly)
30 // 408 Request Timeout
31 // 407 Proxy Authentication Required
32 // 406 Not Acceptable
33 // 405 Method Not Allowed
34 // 404 Not Found
35 // 403 Forbidden
36 // 402 Payment Required
37 // 400 Bad Request
propogateErrorCode(unsigned finalCode,unsigned subResponseCode)38 inline unsigned propogateErrorCode(unsigned finalCode, unsigned subResponseCode)
39 {
40     // We keep a explicit list for error codes that this project often uses
41     // Higher priority codes are in lower indexes
42     constexpr std::array<unsigned, 13> orderedCodes = {
43         500, 507, 503, 502, 501, 401, 412, 409, 406, 405, 404, 403, 400};
44     size_t finalCodeIndex = std::numeric_limits<size_t>::max();
45     size_t subResponseCodeIndex = std::numeric_limits<size_t>::max();
46     for (size_t i = 0; i < orderedCodes.size(); ++i)
47     {
48         if (orderedCodes[i] == finalCode)
49         {
50             finalCodeIndex = i;
51         }
52         if (orderedCodes[i] == subResponseCode)
53         {
54             subResponseCodeIndex = i;
55         }
56     }
57     if (finalCodeIndex != std::numeric_limits<size_t>::max() &&
58         subResponseCodeIndex != std::numeric_limits<size_t>::max())
59     {
60         return finalCodeIndex <= subResponseCodeIndex
61                    ? finalCode
62                    : subResponseCode;
63     }
64     if (subResponseCode == 500 || finalCode == 500)
65     {
66         return 500;
67     }
68     if (subResponseCode > 500 || finalCode > 500)
69     {
70         return std::max(finalCode, subResponseCode);
71     }
72     if (subResponseCode == 401)
73     {
74         return subResponseCode;
75     }
76     return std::max(finalCode, subResponseCode);
77 }
78 
79 // Propagates all error messages into |finalResponse|
propogateError(crow::Response & finalResponse,crow::Response & subResponse)80 inline void propogateError(crow::Response& finalResponse,
81                            crow::Response& subResponse)
82 {
83     // no errors
84     if (subResponse.resultInt() >= 200 && subResponse.resultInt() < 400)
85     {
86         return;
87     }
88     messages::moveErrorsToErrorJson(finalResponse.jsonValue,
89                                     subResponse.jsonValue);
90     finalResponse.result(
91         propogateErrorCode(finalResponse.resultInt(), subResponse.resultInt()));
92 }
93 
94 } // namespace redfish
95