Enable satellite aggregation over POST

This patch enables Redfish satellite aggregation through REST API
POST requests to /redfish/v1/AggregationService/AggregationSources.
Tested successfully on ubuntu22 using multiple python redfish mockup
servers as satellite bmcs.

The previous urlHasPrefix function incorrectly assumed it would receive
a full URL path, but it actually receives individual URL segments.
Replaced with segmentHasPrefix that vastly simplifies prefix matching
in the currentAggregationSources map.

Also removed the correct duplicated route in
redfish-core/lib/aggregation_service.hpp that was causing routing
conflicts.

The hardcoded 5B247A_ fallback remains temporarily and will be
addressed in change 83181 which adds D-Bus satellite support.

Change-Id: I41920ad270abe4b228b43280ea425b80d3f14b50
Signed-off-by: Kamran Hasan <khasan@nvidia.com>
diff --git a/redfish-core/include/redfish_aggregator.hpp b/redfish-core/include/redfish_aggregator.hpp
index 4ed93b0..a318e4e 100644
--- a/redfish-core/include/redfish_aggregator.hpp
+++ b/redfish-core/include/redfish_aggregator.hpp
@@ -1313,11 +1313,7 @@
             {
                 // We've matched a resource collection so this current segment
                 // might contain an aggregation prefix
-                // TODO: This needs to be rethought when we can support multiple
-                // satellites due to
-                // /redfish/v1/AggregationService/AggregationSources/5B247A
-                // being a local resource describing the satellite
-                if (collectionItem.starts_with("5B247A_"))
+                if (segmentHasPrefix(collectionItem))
                 {
                     BMCWEB_LOG_DEBUG("Need to forward a request");
 
@@ -1368,6 +1364,32 @@
         BMCWEB_LOG_DEBUG("Aggregation not required for {}", url.buffer());
         return Result::LocalHandle;
     }
+
+    // Check if the given URL segment matches with any satellite prefix
+    // Assumes the given segment starts with <prefix>_
+    bool segmentHasPrefix(const std::string& urlSegment) const
+    {
+        // TODO: handle this better
+        // For now 5B247A_ wont be in the currentAggregationSources map so
+        // check explicitly for now
+        if (urlSegment.starts_with("5B247A_"))
+        {
+            return true;
+        }
+
+        // Find the first underscore
+        std::size_t underscorePos = urlSegment.find('_');
+        if (underscorePos == std::string::npos)
+        {
+            return false; // No underscore, can't be a satellite prefix
+        }
+
+        // Extract the prefix
+        std::string prefix = urlSegment.substr(0, underscorePos);
+
+        // Check if this prefix exists
+        return currentAggregationSources.contains(prefix);
+    }
 };
 
 } // namespace redfish
diff --git a/redfish-core/lib/aggregation_service.hpp b/redfish-core/lib/aggregation_service.hpp
index cc86405..14c545e 100644
--- a/redfish-core/lib/aggregation_service.hpp
+++ b/redfish-core/lib/aggregation_service.hpp
@@ -242,7 +242,6 @@
     {
         return;
     }
-
     boost::system::result<boost::urls::url> url =
         boost::urls::parse_absolute_uri(hostname);
     if (!url)
@@ -257,16 +256,14 @@
         return;
     }
     crow::utility::setPortDefaults(*url);
-
     std::string prefix = bmcweb::getRandomIdOfLength(8);
     RedfishAggregator::getInstance().currentAggregationSources.emplace(
         prefix, *url);
-
+    BMCWEB_LOG_DEBUG("Emplaced {} with url {}", prefix, url->buffer());
     asyncResp->res.addHeader(
         boost::beast::http::field::location,
         boost::urls::format("/redfish/v1/AggregationSources/{}", prefix)
             .buffer());
-
     messages::created(asyncResp->res);
 }
 
@@ -301,12 +298,6 @@
     BMCWEB_ROUTE(app,
                  "/redfish/v1/AggregationService/AggregationSources/<str>/")
         .privileges(redfish::privileges::getAggregationSource)
-        .methods(boost::beast::http::verb::head)(
-            std::bind_front(handleAggregationSourceHead, std::ref(app)));
-
-    BMCWEB_ROUTE(app,
-                 "/redfish/v1/AggregationService/AggregationSources/<str>/")
-        .privileges(redfish::privileges::getAggregationSource)
         .methods(boost::beast::http::verb::get)(
             std::bind_front(handleAggregationSourceGet, std::ref(app)));