Aggregation: Improve prefix fixup matching
Utilize the new array of top level collection URIs to determine if a
given URI in the response needs to have the aggregation prefix added.
This removes the need to check for specific collections like
/redfish/v1/UpdateService/FirmwareInventory which do not fit the
generic format of /redfish/v1/<collection>.
Future patches will use this same approach to improve the logic for
initially determining if and how a request should be aggregated.
This patch also adds a series of unit tests for the function
responsible for adding a prefix to a given URI. Cases covered include
valid URIs that involve a selection of aggregated resources, top level
collection URIs, other invalid URIs, and URIs with a trailing "/".
Tested:
Unit tests pass.
Signed-off-by: Carson Labrado <clabrado@google.com>
Change-Id: I676983d3c77ae3126c04e9f57ad8698c51df2675
diff --git a/redfish-core/include/aggregation_utils.hpp b/redfish-core/include/aggregation_utils.hpp
index bb1782f..673b568 100644
--- a/redfish-core/include/aggregation_utils.hpp
+++ b/redfish-core/include/aggregation_utils.hpp
@@ -15,52 +15,52 @@
namespace redfish
{
-// Note that each URI actually begins with "/redfish/v1/"
+// Note that each URI actually begins with "/redfish/v1"
// They've been omitted to save space and reduce search time
constexpr std::array<std::string_view, 44> topCollections{
- "AggregationService/Aggregates",
- "AggregationService/AggregationSources",
- "AggregationService/ConnectionMethods",
- "Cables",
- "Chassis",
- "ComponentIntegrity",
- "CompositionService/ActivePool",
- "CompositionService/CompositionReservations",
- "CompositionService/FreePool",
- "CompositionService/ResourceBlocks",
- "CompositionService/ResourceZones",
- "EventService/Subscriptions",
- "Fabrics",
- "Facilities",
- "JobService/Jobs",
- "JobService/Log/Entries",
- "KeyService/NVMeoFKeyPolicies",
- "KeyService/NVMeoFSecrets",
- "LicenseService/Licenses",
- "Managers",
- "NVMeDomains",
- "PowerEquipment/ElectricalBuses",
- "PowerEquipment/FloorPDUs",
- "PowerEquipment/PowerShelves",
- "PowerEquipment/RackPDUs",
- "PowerEquipment/Switchgear",
- "PowerEquipment/TransferSwitches",
- "RegisteredClients",
- "Registries",
- "ResourceBlocks",
- "Storage",
- "StorageServices",
- "StorageSystems",
- "Systems",
- "TaskService/Tasks",
- "TelemetryService/LogService/Entries",
- "TelemetryService/MetricDefinitions",
- "TelemetryService/MetricReportDefinitions",
- "TelemetryService/MetricReports",
- "TelemetryService/Triggers",
- "UpdateService/ClientCertificates",
- "UpdateService/FirmwareInventory",
- "UpdateService/RemoteServerCertificates",
- "UpdateService/SoftwareInventory",
+ "/AggregationService/Aggregates",
+ "/AggregationService/AggregationSources",
+ "/AggregationService/ConnectionMethods",
+ "/Cables",
+ "/Chassis",
+ "/ComponentIntegrity",
+ "/CompositionService/ActivePool",
+ "/CompositionService/CompositionReservations",
+ "/CompositionService/FreePool",
+ "/CompositionService/ResourceBlocks",
+ "/CompositionService/ResourceZones",
+ "/EventService/Subscriptions",
+ "/Fabrics",
+ "/Facilities",
+ "/JobService/Jobs",
+ "/JobService/Log/Entries",
+ "/KeyService/NVMeoFKeyPolicies",
+ "/KeyService/NVMeoFSecrets",
+ "/LicenseService/Licenses",
+ "/Managers",
+ "/NVMeDomains",
+ "/PowerEquipment/ElectricalBuses",
+ "/PowerEquipment/FloorPDUs",
+ "/PowerEquipment/PowerShelves",
+ "/PowerEquipment/RackPDUs",
+ "/PowerEquipment/Switchgear",
+ "/PowerEquipment/TransferSwitches",
+ "/RegisteredClients",
+ "/Registries",
+ "/ResourceBlocks",
+ "/Storage",
+ "/StorageServices",
+ "/StorageSystems",
+ "/Systems",
+ "/TaskService/Tasks",
+ "/TelemetryService/LogService/Entries",
+ "/TelemetryService/MetricDefinitions",
+ "/TelemetryService/MetricReportDefinitions",
+ "/TelemetryService/MetricReports",
+ "/TelemetryService/Triggers",
+ "/UpdateService/ClientCertificates",
+ "/UpdateService/FirmwareInventory",
+ "/UpdateService/RemoteServerCertificates",
+ "/UpdateService/SoftwareInventory",
};
} // namespace redfish
diff --git a/redfish-core/include/redfish_aggregator.hpp b/redfish-core/include/redfish_aggregator.hpp
index 293dad2..bd56d68 100644
--- a/redfish-core/include/redfish_aggregator.hpp
+++ b/redfish-core/include/redfish_aggregator.hpp
@@ -72,53 +72,66 @@
// version mismatches between aggregator and satellite BMCs. For now
// assume that the aggregator has all the schemas and versions that the
// aggregated server has.
- std::string collectionItem;
if (crow::utility::readUrlSegments(thisUrl, "redfish", "v1", "JsonSchemas",
- std::ref(collectionItem),
crow::utility::OrMorePaths()))
{
BMCWEB_LOG_DEBUG << "Skipping JsonSchemas URI prefix fixing";
return;
}
- // We don't need to add prefixes to these URIs since
- // /redfish/v1/UpdateService/ itself is not a collection:
- // /redfish/v1/UpdateService/FirmwareInventory
- // /redfish/v1/UpdateService/SoftwareInventory
- if (crow::utility::readUrlSegments(thisUrl, "redfish", "v1",
- "UpdateService", "FirmwareInventory") ||
- crow::utility::readUrlSegments(thisUrl, "redfish", "v1",
- "UpdateService", "SoftwareInventory"))
+ // The first two segments should be "/redfish/v1". We need to check that
+ // before we can search topCollections
+ if (!crow::utility::readUrlSegments(thisUrl, "redfish", "v1",
+ crow::utility::OrMorePaths()))
{
- BMCWEB_LOG_DEBUG << "Skipping UpdateService URI prefix fixing";
return;
}
- // We need to add a prefix to FirmwareInventory and SoftwareInventory
- // resources:
- // /redfish/v1/UpdateService/FirmwareInventory/<id>
- // /redfish/v1/UpdateService/SoftwareInventory/<id>
- std::string collectionName;
- if (crow::utility::readUrlSegments(
- thisUrl, "redfish", "v1", "UpdateService", std::ref(collectionName),
- std::ref(collectionItem), crow::utility::OrMorePaths()))
+ // Check array adding a segment each time until collection is identified
+ // Add prefix to segment after the collection
+ const boost::urls::segments_view urlSegments = thisUrl.segments();
+ bool addedPrefix = false;
+ boost::urls::url url("/");
+ boost::urls::segments_view::iterator it = urlSegments.begin();
+ const boost::urls::segments_view::const_iterator end = urlSegments.end();
+
+ // Skip past the leading "/redfish/v1"
+ it++;
+ it++;
+ for (; it != end; it++)
{
- collectionItem.insert(0, "_");
- collectionItem.insert(0, prefix);
- item = crow::utility::replaceUrlSegment(thisUrl, 4, collectionItem);
- return;
+ // Trailing "/" will result in an empty segment. In that case we need
+ // to return so we don't apply a prefix to top level collections such
+ // as "/redfish/v1/Chassis/"
+ if ((*it).empty())
+ {
+ return;
+ }
+
+ if (std::binary_search(topCollections.begin(), topCollections.end(),
+ url.buffer()))
+ {
+ std::string collectionItem(prefix);
+ collectionItem += "_" + (*it);
+ url.segments().push_back(collectionItem);
+ it++;
+ addedPrefix = true;
+ break;
+ }
+
+ url.segments().push_back(*it);
}
- // If we reach here then we need to add a prefix to resource IDs that take
- // the general form of "/redfish/v1/<collection>/<id> such as:
- // /redfish/v1/Chassis/foo
- if (crow::utility::readUrlSegments(
- thisUrl, "redfish", "v1", std::ref(collectionName),
- std::ref(collectionItem), crow::utility::OrMorePaths()))
+ // Finish constructing the URL here (if needed) to avoid additional checks
+ for (; it != end; it++)
{
- collectionItem.insert(0, "_");
- collectionItem.insert(0, prefix);
- item = crow::utility::replaceUrlSegment(thisUrl, 3, collectionItem);
+ url.segments().push_back(*it);
+ }
+
+ if (addedPrefix)
+ {
+ url.segments().insert(url.segments().begin(), {"redfish", "v1"});
+ item = url;
}
}
@@ -164,12 +177,6 @@
RedfishAggregator()
{
- // TODO: Remove in future patches, this is here to prevent compiler
- // warnings and get an accurate idea of the increase in the size of the
- // binary.
- BMCWEB_LOG_DEBUG << "There are " << topCollections.size()
- << " top level collections:";
-
getSatelliteConfigs(constructorCallback);
// Setup the retry policy to be used by Redfish Aggregation
@@ -776,7 +783,7 @@
{
using crow::utility::OrMorePaths;
using crow::utility::readUrlSegments;
- const boost::urls::url_view& url = thisReq.urlView;
+ const boost::urls::url_view url = thisReq.urlView;
// UpdateService is the only top level resource that is not a Collection
if (readUrlSegments(url, "redfish", "v1", "UpdateService"))
{