Separate endpoint for MultipartHttpPushUri Update

Currently, the UpdateService uses the same endpoint
"/redfish/v1/UpdateService/update" for both "application/octet-stream"
and "multipart/form-data" HTTP push methods. This change introduces a
dedicated endpoint "/redfish/v1/UpdateService/update-multipart" to
handle multipart firmware updates separately, aligning with the Redfish
spec recommendations[1] and Section 3.1.2 Multipart HTTP push update in
Redfish FW Update White Paper [2].

Spec examples in [1], Section 7.12, shows '/update-multipart' endpoint
as a dedicated URI for MultipartHttpPushUri.

[1] https://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.22.0.pdf
[2] https://www.dmtf.org/sites/default/files/standards/documents/DSP2062_1.0.2.pdf

Tested:
- Verified GET on UpdateService
```
curl -k https://user:pass@<bmc-ip>/redfish/v1/UpdateService
...
"MultipartHttpPushUri": "/redfish/v1/UpdateService/update-multipart",
...
```
- Verified MultipartPushURI update using the new URI.
```
curl -X POST -k https://user:pass@<bmc-ip>/redfish/v1/UpdateService/update-multipart --form 'UpdateParameters={"Targets":["/redfish/v1/Managers/bmc"]};type=application/json' --form "UpdateFile=@<fwpkg>;type=application/octet-stream"
{
  "@odata.id": "/redfish/v1/TaskService/Tasks/1",
  "@odata.type": "#Task.v1_4_3.Task",
  "Id": "1",
  "TaskState": "Running",
  "TaskStatus": "OK"
}
```

Change-Id: I477d7d64571113079d51bff9f188cfa776e6dafa
Signed-off-by: Rajeev Ranjan <ranjan.rajeev1609@gmail.com>
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 1e28dda5..3699264 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -1055,13 +1055,30 @@
 
     BMCWEB_LOG_DEBUG("doPost: contentType={}", contentType);
 
-    // Make sure that content type is application/octet-stream or
-    // multipart/form-data
+    // Make sure that content type is application/octet-stream
     if (bmcweb::asciiIEquals(contentType, "application/octet-stream"))
     {
         doHTTPUpdate(asyncResp, req);
     }
-    else if (contentType.starts_with("multipart/form-data"))
+    else
+    {
+        BMCWEB_LOG_DEBUG("Bad content type specified:{}", contentType);
+        asyncResp->res.result(boost::beast::http::status::bad_request);
+    }
+}
+
+inline void handleUpdateServiceMultipartUpdatePost(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+
+    std::string_view contentType = req.getHeaderValue("Content-Type");
+    // Make sure that content type is multipart/form-data
+    if (contentType.starts_with("multipart/form-data"))
     {
         MultipartParser parser;
 
@@ -1102,7 +1119,7 @@
     asyncResp->res.jsonValue["HttpPushUri"] =
         "/redfish/v1/UpdateService/update";
     asyncResp->res.jsonValue["MultipartHttpPushUri"] =
-        "/redfish/v1/UpdateService/update";
+        "/redfish/v1/UpdateService/update-multipart";
 
     // UpdateService cannot be disabled
     asyncResp->res.jsonValue["ServiceEnabled"] = true;
@@ -1358,6 +1375,11 @@
         .methods(boost::beast::http::verb::post)(
             std::bind_front(handleUpdateServicePost, std::ref(app)));
 
+    BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/update-multipart/")
+        .privileges(redfish::privileges::postUpdateService)
+        .methods(boost::beast::http::verb::post)(std::bind_front(
+            handleUpdateServiceMultipartUpdatePost, std::ref(app)));
+
     BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/FirmwareInventory/")
         .privileges(redfish::privileges::getSoftwareInventoryCollection)
         .methods(boost::beast::http::verb::get)(std::bind_front(