1 #include "error_message_utils.hpp" 2 3 #include "logging.hpp" 4 5 #include <nlohmann/json.hpp> 6 7 #include <string> 8 #include <string_view> 9 10 namespace redfish 11 { 12 13 namespace messages 14 { 15 16 void addMessageToErrorJson(nlohmann::json& target, 17 const nlohmann::json& message) 18 { 19 auto& error = target["error"]; 20 21 // If this is the first error message, fill in the information from the 22 // first error message to the top level struct 23 if (!error.is_object()) 24 { 25 auto messageIdIterator = message.find("MessageId"); 26 if (messageIdIterator == message.end()) 27 { 28 BMCWEB_LOG_CRITICAL( 29 "Attempt to add error message without MessageId"); 30 return; 31 } 32 33 auto messageFieldIterator = message.find("Message"); 34 if (messageFieldIterator == message.end()) 35 { 36 BMCWEB_LOG_CRITICAL("Attempt to add error message without Message"); 37 return; 38 } 39 error["code"] = *messageIdIterator; 40 error["message"] = *messageFieldIterator; 41 } 42 else 43 { 44 // More than 1 error occurred, so the message has to be generic 45 error["code"] = std::string(messageVersionPrefix) + "GeneralError"; 46 error["message"] = "A general error has occurred. See Resolution for " 47 "information on how to resolve the error."; 48 } 49 50 // This check could technically be done in the default construction 51 // branch above, but because we need the pointer to the extended info field 52 // anyway, it's more efficient to do it here. 53 auto& extendedInfo = error[messages::messageAnnotation]; 54 if (!extendedInfo.is_array()) 55 { 56 extendedInfo = nlohmann::json::array(); 57 } 58 59 extendedInfo.push_back(message); 60 } 61 62 void moveErrorsToErrorJson(nlohmann::json& target, nlohmann::json& source) 63 { 64 if (!source.is_object()) 65 { 66 return; 67 } 68 auto errorIt = source.find("error"); 69 if (errorIt == source.end()) 70 { 71 // caller puts error message in root 72 messages::addMessageToErrorJson(target, source); 73 source.clear(); 74 return; 75 } 76 auto extendedInfoIt = errorIt->find(messages::messageAnnotation); 77 if (extendedInfoIt == errorIt->end()) 78 { 79 return; 80 } 81 const nlohmann::json::array_t* extendedInfo = 82 (*extendedInfoIt).get_ptr<const nlohmann::json::array_t*>(); 83 if (extendedInfo == nullptr) 84 { 85 source.erase(errorIt); 86 return; 87 } 88 for (const nlohmann::json& message : *extendedInfo) 89 { 90 addMessageToErrorJson(target, message); 91 } 92 source.erase(errorIt); 93 } 94 95 void addMessageToJsonRoot(nlohmann::json& target, const nlohmann::json& message) 96 { 97 if (!target[messages::messageAnnotation].is_array()) 98 { 99 // Force object to be an array 100 target[messages::messageAnnotation] = nlohmann::json::array(); 101 } 102 103 target[messages::messageAnnotation].push_back(message); 104 } 105 106 void addMessageToJson(nlohmann::json& target, const nlohmann::json& message, 107 std::string_view fieldPath) 108 { 109 std::string extendedInfo(fieldPath); 110 extendedInfo += messages::messageAnnotation; 111 112 nlohmann::json& field = target[extendedInfo]; 113 if (!field.is_array()) 114 { 115 // Force object to be an array 116 field = nlohmann::json::array(); 117 } 118 119 // Object exists and it is an array so we can just push in the message 120 field.push_back(message); 121 } 122 123 } // namespace messages 124 } // namespace redfish 125