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