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 std::string name = req.urlView.segments().back(); 42 // Note, if we hit the wildcard route, we don't know the "type" the user was 43 // actually requesting, but giving them a return with an empty string is 44 // still better than nothing. 45 messages::resourceNotFound(asyncResp->res, "", name); 46 } 47 48 inline void redfish405(App& app, const crow::Request& req, 49 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 50 const std::string& path) 51 { 52 // If we fall to this route, we didn't have a more specific route, so return 53 // 405 54 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 55 { 56 return; 57 } 58 59 BMCWEB_LOG_ERROR << "405 on path " << path; 60 asyncResp->res.result(boost::beast::http::status::method_not_allowed); 61 if (req.method() == boost::beast::http::verb::delete_) 62 { 63 messages::resourceCannotBeDeleted(asyncResp->res); 64 } 65 else 66 { 67 messages::operationNotAllowed(asyncResp->res); 68 } 69 } 70 71 inline void 72 jsonSchemaIndexGet(App& app, const crow::Request& req, 73 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 74 { 75 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 76 { 77 return; 78 } 79 nlohmann::json& json = asyncResp->res.jsonValue; 80 json["@odata.id"] = "/redfish/v1/JsonSchemas"; 81 json["@odata.context"] = 82 "/redfish/v1/$metadata#JsonSchemaFileCollection.JsonSchemaFileCollection"; 83 json["@odata.type"] = "#JsonSchemaFileCollection.JsonSchemaFileCollection"; 84 json["Name"] = "JsonSchemaFile Collection"; 85 json["Description"] = "Collection of JsonSchemaFiles"; 86 nlohmann::json::array_t members; 87 for (const std::string_view schema : schemas) 88 { 89 nlohmann::json::object_t member; 90 member["@odata.id"] = crow::utility::urlFromPieces( 91 "redfish", "v1", "JsonSchemas", schema); 92 members.push_back(std::move(member)); 93 } 94 json["Members"] = std::move(members); 95 json["Members@odata.count"] = schemas.size(); 96 } 97 98 inline void jsonSchemaGet(App& app, const crow::Request& req, 99 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 100 const std::string& schema) 101 { 102 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 103 { 104 return; 105 } 106 107 if (std::find(schemas.begin(), schemas.end(), schema) == schemas.end()) 108 { 109 messages::resourceNotFound(asyncResp->res, "JsonSchemaFile", schema); 110 return; 111 } 112 113 nlohmann::json& json = asyncResp->res.jsonValue; 114 json["@odata.context"] = 115 "/redfish/v1/$metadata#JsonSchemaFile.JsonSchemaFile"; 116 json["@odata.id"] = 117 crow::utility::urlFromPieces("redfish", "v1", "JsonSchemas", schema); 118 json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile"; 119 json["Name"] = schema + " Schema File"; 120 json["Description"] = schema + " Schema File Location"; 121 json["Id"] = schema; 122 std::string schemaName = "#"; 123 schemaName += schema; 124 schemaName += "."; 125 schemaName += schema; 126 json["Schema"] = std::move(schemaName); 127 constexpr std::array<std::string_view, 1> languages{"en"}; 128 json["Languages"] = languages; 129 json["Languages@odata.count"] = languages.size(); 130 131 nlohmann::json::array_t locationArray; 132 nlohmann::json::object_t locationEntry; 133 locationEntry["Language"] = "en"; 134 locationEntry["PublicationUri"] = 135 "http://redfish.dmtf.org/schemas/v1/" + schema + ".json"; 136 locationEntry["Uri"] = crow::utility::urlFromPieces( 137 "redfish", "v1", "JsonSchemas", schema, std::string(schema) + ".json"); 138 139 locationArray.emplace_back(locationEntry); 140 141 json["Location"] = std::move(locationArray); 142 json["Location@odata.count"] = 1; 143 } 144 145 inline void requestRoutesRedfish(App& app) 146 { 147 BMCWEB_ROUTE(app, "/redfish/") 148 .methods(boost::beast::http::verb::get)( 149 std::bind_front(redfishGet, std::ref(app))); 150 151 BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/<str>/") 152 .privileges(redfish::privileges::getJsonSchemaFileCollection) 153 .methods(boost::beast::http::verb::get)( 154 std::bind_front(jsonSchemaGet, std::ref(app))); 155 156 BMCWEB_ROUTE(app, "/redfish/v1/JsonSchemas/") 157 .privileges(redfish::privileges::getJsonSchemaFile) 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() 164 .privileges(redfish::privileges::privilegeSetLogin)( 165 std::bind_front(redfish404, std::ref(app))); 166 167 BMCWEB_ROUTE(app, "/redfish/<path>") 168 .methodNotAllowed() 169 .privileges(redfish::privileges::privilegeSetLogin)( 170 std::bind_front(redfish405, std::ref(app))); 171 } 172 173 } // namespace redfish 174