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 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| 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