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(