summaryrefslogtreecommitdiff
path: root/redfish-core
diff options
context:
space:
mode:
authorEd Tanous <ed@tanous.net>2023-08-07 22:02:40 +0300
committerEd Tanous <ed@tanous.net>2023-10-31 20:43:04 +0300
commit27b0cf90f6cba207837f5c263a45c6ea5651975b (patch)
tree314cda7432edfe44fdd1297664db1399a1d6ba22 /redfish-core
parent522377dcb85082da598403e104a44d621b4c2bb4 (diff)
downloadbmcweb-27b0cf90f6cba207837f5c263a45c6ea5651975b.tar.xz
Move to file_body in boost
As is, it reads the whole file into memory before sending it. While fairly fast for the user, this wastes ram, and makes bmcweb less useful on less capable systems. This patch enables using the boost::beast::http::file_body type, which has more efficient serialization semantics than using a std::string. To do this, it adds a openFile() handler to http::Response, which can be used to properly open a file. Once the file is opened, the existing string body is ignored, and the file payload is sent instead. openFile() also returns success or failure, to allow users to properly handle 404s and other errors. To prove that it works, I moved over every instance of direct use of the body() method over to using this, including the webasset handler. The webasset handler specifically should help with system load when doing an initial page load of the webui. Tested: Redfish service validator passes. Change-Id: Ic7ea9ffefdbc81eb985de7edc0fac114822994ad Signed-off-by: Ed Tanous <ed@tanous.net>
Diffstat (limited to 'redfish-core')
-rw-r--r--redfish-core/include/redfish_aggregator.hpp24
-rw-r--r--redfish-core/lib/log_services.hpp23
2 files changed, 23 insertions, 24 deletions
diff --git a/redfish-core/include/redfish_aggregator.hpp b/redfish-core/include/redfish_aggregator.hpp
index 335c64e694..680e1b0c05 100644
--- a/redfish-core/include/redfish_aggregator.hpp
+++ b/redfish-core/include/redfish_aggregator.hpp
@@ -728,7 +728,7 @@ class RedfishAggregator
std::function<void(crow::Response&)> cb =
std::bind_front(processResponse, prefix, asyncResp);
- std::string data = thisReq.req.body();
+ std::string data = thisReq.body();
boost::urls::url url(sat->second);
url.set_path(path);
if (targetURI.has_query())
@@ -756,7 +756,7 @@ class RedfishAggregator
{
url.set_query(thisReq.url().query());
}
- std::string data = thisReq.req.body();
+ std::string data = thisReq.body();
client.sendDataWithCallback(std::move(data), url, thisReq.fields(),
thisReq.method(), cb);
}
@@ -781,7 +781,7 @@ class RedfishAggregator
boost::urls::url url(sat.second);
url.set_path(thisReq.url().path());
- std::string data = thisReq.req.body();
+ std::string data = thisReq.body();
client.sendDataWithCallback(std::move(data), url, thisReq.fields(),
thisReq.method(), cb);
@@ -874,8 +874,8 @@ class RedfishAggregator
if (boost::iequals(contentType, "application/json") ||
boost::iequals(contentType, "application/json; charset=utf-8"))
{
- nlohmann::json jsonVal = nlohmann::json::parse(resp.body(), nullptr,
- false);
+ nlohmann::json jsonVal = nlohmann::json::parse(*resp.body(),
+ nullptr, false);
if (jsonVal.is_discarded())
{
BMCWEB_LOG_ERROR("Error parsing satellite response as JSON");
@@ -898,7 +898,7 @@ class RedfishAggregator
{
// We allow any Content-Type that is not "application/json" now
asyncResp->res.result(resp.result());
- asyncResp->res.write(resp.body());
+ asyncResp->res.copyBody(resp);
}
addAggregatedHeaders(asyncResp->res, resp, prefix);
}
@@ -927,7 +927,7 @@ class RedfishAggregator
if (asyncResp->res.resultInt() != 200)
{
asyncResp->res.result(resp.result());
- asyncResp->res.write(resp.body());
+ asyncResp->res.copyBody(resp);
}
return;
}
@@ -938,8 +938,8 @@ class RedfishAggregator
if (boost::iequals(contentType, "application/json") ||
boost::iequals(contentType, "application/json; charset=utf-8"))
{
- nlohmann::json jsonVal = nlohmann::json::parse(resp.body(), nullptr,
- false);
+ nlohmann::json jsonVal = nlohmann::json::parse(*resp.body(),
+ nullptr, false);
if (jsonVal.is_discarded())
{
BMCWEB_LOG_ERROR("Error parsing satellite response as JSON");
@@ -1061,7 +1061,7 @@ class RedfishAggregator
if (asyncResp->res.resultInt() != 200)
{
asyncResp->res.result(resp.result());
- asyncResp->res.write(resp.body());
+ asyncResp->res.copyBody(resp);
}
return;
}
@@ -1073,8 +1073,8 @@ class RedfishAggregator
boost::iequals(contentType, "application/json; charset=utf-8"))
{
bool addedLinks = false;
- nlohmann::json jsonVal = nlohmann::json::parse(resp.body(), nullptr,
- false);
+ nlohmann::json jsonVal = nlohmann::json::parse(*resp.body(),
+ nullptr, false);
if (jsonVal.is_discarded())
{
BMCWEB_LOG_ERROR("Error parsing satellite response as JSON");
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 116bc8acb8..54284cfef2 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -766,8 +766,9 @@ inline void
return;
}
- asyncResp->res.body().resize(static_cast<size_t>(size), '\0');
- rc = read(fd, asyncResp->res.body().data(), asyncResp->res.body().size());
+ std::string body;
+ body.resize(static_cast<size_t>(size), '\0');
+ rc = read(fd, body.data(), body.size());
if ((rc == -1) || (rc != size))
{
BMCWEB_LOG_ERROR("Failed to read in file");
@@ -776,16 +777,17 @@ inline void
return;
}
close(fd);
-
if (downloadEntryType == "System")
{
- // We need to encode the data. Doing it this way saves the other paths
- // from having to make a copy into a temporary variable.
- asyncResp->res.body() =
- crow::utility::base64encode(asyncResp->res.body());
+ // Base64 encode response.
+ asyncResp->res.write(crow::utility::base64encode(body));
asyncResp->res.addHeader(
boost::beast::http::field::content_transfer_encoding, "Base64");
}
+ else
+ {
+ asyncResp->res.write(std::move(body));
+ }
asyncResp->res.addHeader(boost::beast::http::field::content_type,
"application/octet-stream");
@@ -3545,14 +3547,11 @@ inline void requestRoutesCrashdumpFile(App& app)
return;
}
- if (!std::filesystem::exists(dbusFilepath))
+ if (!asyncResp->res.openFile(dbusFilepath))
{
messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
return;
}
- std::ifstream ifs(dbusFilepath, std::ios::in | std::ios::binary);
- asyncResp->res.body() =
- std::string(std::istreambuf_iterator<char>{ifs}, {});
// Configure this to be a file download when accessed
// from a browser
@@ -4314,7 +4313,7 @@ inline void requestRoutesPostCodesEntryAdditionalData(App& app)
"application/octet-stream");
asyncResp->res.addHeader(
boost::beast::http::field::content_transfer_encoding, "Base64");
- asyncResp->res.body() = crow::utility::base64encode(strData);
+ asyncResp->res.write(crow::utility::base64encode(strData));
},
"xyz.openbmc_project.State.Boot.PostCode0",
"/xyz/openbmc_project/State/Boot/PostCode0",