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