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, "JsonSchemaFile", schema); 111 return; 112 } 113 114 nlohmann::json& json = asyncResp->res.jsonValue; 115 json["@odata.context"] = 116 "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile"; 117 json["@odata.id"] = 118 crow::utility::urlFromPieces("redfish", "v1", "JsonSchemas", schema); 119 json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile"; 120 json["Name"] = schema + " Schema File"; 121 json["Description"] = schema + " Schema File Location"; 122 json["Id"] = schema; 123 std::string schemaName = "#"; 124 schemaName += schema; 125 schemaName += "."; 126 schemaName += schema; 127 json["Schema"] = std::move(schemaName); 128 constexpr std::array<std::string_view, 1> languages{"en"}; 129 json["Languages"] = languages; 130 json["Languages@odata.count"] = languages.size(); 131 132 nlohmann::json::array_t locationArray; 133 nlohmann::json::object_t locationEntry; 134 locationEntry["Language"] = "en"; 135 locationEntry["PublicationUri"] = 136 "http://redfish.dmtf.org/schemas/v1/" + schema + ".json"; 137 locationEntry["Uri"] = crow::utility::urlFromPieces( 138 "redfish", "v1", "JsonSchemas", schema, std::string(schema) + ".json"); 139 140 locationArray.emplace_back(locationEntry); 141 142 json["Location"] = std::move(locationArray); 143 json["Location@odata.count"] = 1; 144 } 145 146 inline void requestRoutesRedfish(App& app) 147 { 148 BMCWEB_ROUTE(app, "/redfish/") 149 .methods(boost::beast::http::verb::get)( 150 std::bind_front(redfishGet, std::ref(app))); 151 152 BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/<str>/") 153 .privileges(redfish::privileges::getJsonSchemaFileCollection) 154 .methods(boost::beast::http::verb::get)( 155 std::bind_front(jsonSchemaGet, std::ref(app))); 156 157 BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/") 158 .privileges(redfish::privileges::getJsonSchemaFile) 159 .methods(boost::beast::http::verb::get)( 160 std::bind_front(jsonSchemaIndexGet, std::ref(app))); 161 162 // Note, this route must always be registered last 163 BMCWEB_ROUTE(app, "/redfish/<path>") 164 .notFound() 165 .privileges(redfish::privileges::privilegeSetLogin)( 166 std::bind_front(redfish404, std::ref(app))); 167 168 BMCWEB_ROUTE(app, "/redfish/<path>") 169 .methodNotAllowed() 170 .privileges(redfish::privileges::privilegeSetLogin)( 171 std::bind_front(redfish405, std::ref(app))); 172 } 173 174 } // namespace redfish 175