Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions http/app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,20 @@ class App
{
return router.getRoutes(parent);
}
void prepareRequestBody(boost::beast::http::request<bmcweb::HttpBody>& req)
{
auto result = boost::urls::parse_relative_ref(req.target());
if (!result)
{
return;
}
auto url = *result;
auto routeRes = router.findRoute(url, req.method());
if (routeRes.route.rule)
{
routeRes.route.rule->prepareBody(req);
}
}

std::optional<server_type> server;

Expand Down
21 changes: 20 additions & 1 deletion http/http_body.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ class HttpBody::value_type
{
return fileHandle.fileHandle;
}
boost::beast::file_posix& file()
{
return fileHandle.fileHandle;
}

std::string& str()
{
Expand Down Expand Up @@ -270,7 +274,22 @@ class HttpBody::reader
for (const auto b : boost::beast::buffers_range_ref(buffers))
{
const char* ptr = static_cast<const char*>(b.data());
value.str() += std::string_view(ptr, b.size());
if (value.file().is_open())
{
boost::system::error_code writeEc;
value.file().write(ptr, b.size(), writeEc);
if (writeEc)
{
BMCWEB_LOG_ERROR("Failed to write to file {}",
writeEc.message());
ec = writeEc;
return 0;
}
}
else
{
value.str() += std::string_view(ptr, b.size());
}
}
ec = {};
return extra;
Expand Down
3 changes: 2 additions & 1 deletion http/http_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ class Connection :
handle();
return;
}
handler->prepareRequestBody(parser->get());

doRead();
}
Expand Down Expand Up @@ -923,7 +924,7 @@ class Connection :
return;
}

std::chrono::seconds timeout(15);
std::chrono::seconds timeout(15 * 60);

std::weak_ptr<Connection<Adaptor, Handler>> weakSelf = weak_from_this();
timer.expires_after(timeout);
Expand Down
14 changes: 9 additions & 5 deletions http/routing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,8 @@ class Router
}
return route;
}

FindRouteResponse findRoute(const Request& req) const
FindRouteResponse findRoute(const boost::urls::url& url,
boost::beast::http::verb bv) const
{
FindRouteResponse findRoute;

Expand All @@ -527,7 +527,7 @@ class Router
// Make sure it's safe to deference the array at that index
static_assert(
maxVerbIndex < std::tuple_size_v<decltype(perMethods)>);
FindRoute route = findRouteByPerMethod(req.url().encoded_path(),
FindRoute route = findRouteByPerMethod(url.encoded_path(),
perMethods[perMethodIndex]);
if (route.rule == nullptr)
{
Expand All @@ -541,7 +541,7 @@ class Router
findRoute.allowHeader += httpVerbToString(thisVerb);
}

std::optional<HttpVerb> verb = httpVerbFromBoost(req.method());
std::optional<HttpVerb> verb = httpVerbFromBoost(bv);
if (!verb)
{
return findRoute;
Expand All @@ -552,7 +552,7 @@ class Router
return findRoute;
}

FindRoute route = findRouteByPerMethod(req.url().encoded_path(),
FindRoute route = findRouteByPerMethod(url.encoded_path(),
perMethods[reqMethodIndex]);
if (route.rule != nullptr)
{
Expand All @@ -561,6 +561,10 @@ class Router

return findRoute;
}
FindRouteResponse findRoute(const Request& request) const
{
return findRoute(request.url(), request.method());
}

template <typename Adaptor>
void handleUpgrade(const std::shared_ptr<Request>& req,
Expand Down
3 changes: 3 additions & 0 deletions http/routing/baserule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ class BaseRule
}
return false;
}
virtual void prepareBody(
boost::beast::http::request<bmcweb::HttpBody>& /*req*/)
{}

size_t methodsBitfield{1 << static_cast<size_t>(HttpVerb::Get)};
static_assert(std::numeric_limits<decltype(methodsBitfield)>::digits >
Expand Down
22 changes: 22 additions & 0 deletions http/routing/taggedrule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,26 @@ class TaggedRule :

handler = std::forward<Func>(f);
}
template <typename Func>
self_t& onPrepareRequestBody(Func&& f)
{
BMCWEB_LOG_DEBUG("onPrepareRequestBody");
static_assert(
std::is_invocable_v<Func, Request::Body&>,
"prepare body type is mismatched void(boost::beast::http::request<bmcweb::HttpBody>&)");

prepareRequestBody = std::forward<Func>(f);
return *this;
}
void prepareBody(
boost::beast::http::request<bmcweb::HttpBody>& req) override
{
BMCWEB_LOG_DEBUG("prepareBody");
if (prepareRequestBody)
{
prepareRequestBody(req);
}
}

void handle(const Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Expand Down Expand Up @@ -86,5 +106,7 @@ class TaggedRule :
std::function<void(const crow::Request&,
const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>
handler;
std::function<void(boost::beast::http::request<bmcweb::HttpBody>& req)>
prepareRequestBody;
};
} // namespace crow
57 changes: 54 additions & 3 deletions redfish-core/lib/update_service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,36 @@ inline void handleUpdateServiceSimpleUpdateAction(

BMCWEB_LOG_DEBUG("Exit UpdateService.SimpleUpdate doPost");
}
inline void uploadImageFileFromDowloaded(crow::Response& res)
{
std::filesystem::path sourceDir("/tmp/images_downloaded");
std::filesystem::path destDir("/tmp/images");

try
{
for (const auto& entry : std::filesystem::directory_iterator(sourceDir))
{
if (entry.is_regular_file())
{
std::filesystem::path sourceFile = entry.path();
std::filesystem::path destFile =
destDir / sourceFile.filename();

std::filesystem::rename(sourceFile, destFile);
BMCWEB_LOG_DEBUG("Moved file from {} to {}",
sourceFile.string(), destFile.string());
return; // Move only the first file
}
}
BMCWEB_LOG_ERROR("No files found in {}", sourceDir.string());
messages::internalError(res);
}
catch (const std::filesystem::filesystem_error& e)
{
BMCWEB_LOG_ERROR("Failed to move file: {}", e.what());
messages::internalError(res);
}
}

inline void uploadImageFile(crow::Response& res, std::string_view body)
{
Expand Down Expand Up @@ -1135,11 +1165,9 @@ inline void doHTTPUpdate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
}
else
{
// Setup callback for when new software detected
// Setup callback for when new software detected
monitorForSoftwareAvailable(asyncResp, req, url);

uploadImageFile(asyncResp->res, req.body());
uploadImageFileFromDowloaded(asyncResp->res);
}
}

Expand Down Expand Up @@ -1465,6 +1493,17 @@ inline void requestRoutesUpdateService(App& app)
app,
"/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate/")
.privileges(redfish::privileges::postUpdateService)
.onPrepareRequestBody([](auto& req) {
std::string filename("/tmp/images_downloaded/");
filename.append(bmcweb::getRandomUUID());
boost::system::error_code ec1;
req.body().open(filename.data(), boost::beast::file_mode::write,
ec1);
if (ec1)
{
BMCWEB_LOG_ERROR("Failed to open file: {}", ec1.message());
}
})
.methods(boost::beast::http::verb::post)(std::bind_front(
handleUpdateServiceSimpleUpdateAction, std::ref(app)));
}
Expand All @@ -1480,6 +1519,18 @@ inline void requestRoutesUpdateService(App& app)

BMCWEB_ROUTE(app, "/redfish/v1/UpdateService/update/")
.privileges(redfish::privileges::postUpdateService)
.onPrepareRequestBody(
[](boost::beast::http::request<bmcweb::HttpBody>& req) {
std::string filename("/tmp/images_downloaded/");
filename.append(bmcweb::getRandomUUID());
boost::system::error_code ec1;
req.body().open(filename.data(), boost::beast::file_mode::write,
ec1);
if (ec1)
{
BMCWEB_LOG_ERROR("Failed to open file: {}", ec1.message());
}
})
.methods(boost::beast::http::verb::post)(std::bind_front(
[&app](App&, const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
Expand Down