#pragma once #include "bmcweb_config.h" #include "app.hpp" #include "async_resp.hpp" #include "http_request.hpp" #include "persistent_data.hpp" #include "query.hpp" #include "registries/privilege_registry.hpp" #include "utils/systemd_utils.hpp" #include #include namespace redfish { inline std::string getMetadataPieceForFile(const std::filesystem::path& filename) { std::string xml; tinyxml2::XMLDocument doc; std::string pathStr = filename.string(); if (doc.LoadFile(pathStr.c_str()) != tinyxml2::XML_SUCCESS) { BMCWEB_LOG_ERROR("Failed to open XML file {}", pathStr); return ""; } xml += std::format(" \n", filename.filename().string()); // std::string edmx = "{http://docs.oasis-open.org/odata/ns/edmx}"; // std::string edm = "{http://docs.oasis-open.org/odata/ns/edm}"; const char* edmx = "edmx:Edmx"; for (tinyxml2::XMLElement* edmxNode = doc.FirstChildElement(edmx); edmxNode != nullptr; edmxNode = edmxNode->NextSiblingElement(edmx)) { const char* dataServices = "edmx:DataServices"; for (tinyxml2::XMLElement* node = edmxNode->FirstChildElement(dataServices); node != nullptr; node = node->NextSiblingElement(dataServices)) { BMCWEB_LOG_DEBUG("Got data service for {}", pathStr); const char* schemaTag = "Schema"; for (tinyxml2::XMLElement* schemaNode = node->FirstChildElement(schemaTag); schemaNode != nullptr; schemaNode = schemaNode->NextSiblingElement(schemaTag)) { std::string ns = schemaNode->Attribute("Namespace"); // BMCWEB_LOG_DEBUG("Found namespace {}", ns); std::string alias; if (std::string_view(ns).starts_with("RedfishExtensions")) { alias = " Alias=\"Redfish\""; } xml += std::format( " \n", ns, alias); } } } xml += " \n"; return xml; } inline void handleMetadataGet(App& /*app*/, const crow::Request& /*req*/, const std::shared_ptr& asyncResp) { std::filesystem::path schema("/usr/share/www/redfish/v1/schema"); std::error_code ec; auto iter = std::filesystem::directory_iterator(schema, ec); if (ec) { BMCWEB_LOG_ERROR("Failed to open XML folder {}", schema.string()); asyncResp->res.result( boost::beast::http::status::internal_server_error); return; } std::string xml; xml += "\n"; xml += "\n"; for (const auto& dirEntry : iter) { std::string path = dirEntry.path().filename(); if (!std::string_view(path).ends_with("_v1.xml")) { continue; } std::string metadataPiece = getMetadataPieceForFile(dirEntry.path()); if (metadataPiece.empty()) { asyncResp->res.result( boost::beast::http::status::internal_server_error); return; } xml += metadataPiece; } xml += " \n"; xml += " \n"; xml += " \n"; xml += " \n"; xml += " \n"; xml += "\n"; asyncResp->res.addHeader(boost::beast::http::field::content_type, "application/xml"); asyncResp->res.write(std::move(xml)); } inline void requestRoutesMetadata(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/$metadata") .methods(boost::beast::http::verb::get)( std::bind_front(handleMetadataGet, std::ref(app))); } } // namespace redfish