1 #pragma once 2 3 #include "error_messages.hpp" 4 #include "utility.hpp" 5 6 #include <app.hpp> 7 #include <http_request.hpp> 8 #include <http_response.hpp> 9 #include <schemas.hpp> 10 11 #include <string> 12 13 namespace redfish 14 { 15 16 inline void redfishGet(App& app, const crow::Request& req, 17 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 18 { 19 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 20 { 21 return; 22 } 23 asyncResp->res.jsonValue["v1"] = "/redfish/v1/"; 24 } 25 26 inline void redfish404(App& app, const crow::Request& req, 27 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 28 const std::string& path) 29 { 30 asyncResp->res.addHeader(boost::beast::http::field::allow, ""); 31 32 // If we fall to this route, we didn't have a more specific route, so return 33 // 404 34 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 35 { 36 return; 37 } 38 39 BMCWEB_LOG_ERROR << "404 on path " << path; 40 41 boost::urls::string_value name = req.urlView.segments().back(); 42 std::string_view nameStr(name.data(), name.size()); 43 // Note, if we hit the wildcard route, we don't know the "type" the user was 44 // actually requesting, but giving them a return with an empty string is 45 // still better than nothing. 46 messages::resourceNotFound(asyncResp->res, "", nameStr); 47 } 48 49 inline void redfish405(App& app, const crow::Request& req, 50 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 51 const std::string& path) 52 { 53 // If we fall to this route, we didn't have a more specific route, so return 54 // 405 55 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 56 { 57 return; 58 } 59 60 BMCWEB_LOG_ERROR << "405 on path " << path; 61 asyncResp->res.result(boost::beast::http::status::method_not_allowed); 62 if (req.method() == boost::beast::http::verb::delete_) 63 { 64 messages::resourceCannotBeDeleted(asyncResp->res); 65 } 66 else 67 { 68 messages::operationNotAllowed(asyncResp->res); 69 } 70 } 71 72 inline void 73 jsonSchemaIndexGet(App& app, const crow::Request& req, 74 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 75 { 76 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 77 { 78 return; 79 } 80 nlohmann::json& json = asyncResp->res.jsonValue; 81 json["@odata.id"] = "/redfish/v1/JsonSchemas"; 82 json["@odata.context"] = 83 "/redfish/v1/$metadata#JsonSchemaFileCollection.JsonSchemaFileCollection"; 84 json["@odata.type"] = "#JsonSchemaFileCollection.JsonSchemaFileCollection"; 85 json["Name"] = "JsonSchemaFile Collection"; 86 json["Description"] = "Collection of JsonSchemaFiles"; 87 nlohmann::json::array_t members; 88 for (const std::string_view schema : schemas) 89 { 90 nlohmann::json::object_t member; 91 member["@odata.id"] = crow::utility::urlFromPieces( 92 "redfish", "v1", "JsonSchemas", schema); 93 members.push_back(std::move(member)); 94 } 95 json["Members"] = std::move(members); 96 json["Members@odata.count"] = schemas.size(); 97 } 98 99 inline void jsonSchemaGet(App& app, const crow::Request& req, 100 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 101 const std::string& schema) 102 { 103 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 104 { 105 return; 106 } 107 108 if (std::find(schemas.begin(), schemas.end(), schema) == schemas.end()) 109 { 110 messages::resourceNotFound(asyncResp->res, 111 "JsonSchemaFile.JsonSchemaFile", schema); 112 return; 113 } 114 115 nlohmann::json& json = asyncResp->res.jsonValue; 116 json["@odata.context"] = 117 "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile"; 118 json["@odata.id"] = 119 crow::utility::urlFromPieces("redfish", "v1", "JsonSchemas", schema); 120 json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile"; 121 json["Name"] = schema + " Schema File"; 122 json["Description"] = schema + " Schema File Location"; 123 json["Id"] = schema; 124 std::string schemaName = "#"; 125 schemaName += schema; 126 schemaName += "."; 127 schemaName += schema; 128 json["Schema"] = std::move(schemaName); 129 constexpr std::array<std::string_view, 1> languages{"en"}; 130 json["Languages"] = languages; 131 json["Languages@odata.count"] = languages.size(); 132 133 nlohmann::json::array_t locationArray; 134 nlohmann::json::object_t locationEntry; 135 locationEntry["Language"] = "en"; 136 locationEntry["PublicationUri"] = 137 "http://redfish.dmtf.org/schemas/v1/" + schema + ".json"; 138 locationEntry["Uri"] = crow::utility::urlFromPieces( 139 "redfish", "v1", "JsonSchemas", schema, std::string(schema) + ".json"); 140 141 locationArray.emplace_back(locationEntry); 142 143 json["Location"] = std::move(locationArray); 144 json["Location@odata.count"] = 1; 145 } 146 147 inline void requestRoutesRedfish(App& app) 148 { 149 BMCWEB_ROUTE(app, "/redfish/") 150 .methods(boost::beast::http::verb::get)( 151 std::bind_front(redfishGet, std::ref(app))); 152 153 BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/<str>/") 154 .methods(boost::beast::http::verb::get)( 155 std::bind_front(jsonSchemaGet, std::ref(app))); 156 157 BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/") 158 .methods(boost::beast::http::verb::get)( 159 std::bind_front(jsonSchemaIndexGet, std::ref(app))); 160 161 // Note, this route must always be registered last 162 BMCWEB_ROUTE(app, "/redfish/<path>") 163 .notFound()(std::bind_front(redfish404, std::ref(app))); 164 165 BMCWEB_ROUTE(app, "/redfish/<path>") 166 .methodNotAllowed()(std::bind_front(redfish405, std::ref(app))); 167 } 168 169 } // namespace redfish 170