diff options
-rw-r--r-- | http/app.hpp | 6 | ||||
-rw-r--r-- | http/http_connection.hpp | 19 | ||||
-rw-r--r-- | http/routing.hpp | 44 |
3 files changed, 42 insertions, 27 deletions
diff --git a/http/app.hpp b/http/app.hpp index d3afe60f05..a2892ced94 100644 --- a/http/app.hpp +++ b/http/app.hpp @@ -58,9 +58,11 @@ class App App& operator=(const App&&) = delete; template <typename Adaptor> - void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor) + void handleUpgrade(const Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + Adaptor&& adaptor) { - router.handleUpgrade(req, res, std::forward<Adaptor>(adaptor)); + router.handleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor)); } void handle(Request& req, diff --git a/http/http_connection.hpp b/http/http_connection.hpp index c28cde37ae..d5d02e545a 100644 --- a/http/http_connection.hpp +++ b/http/http_connection.hpp @@ -249,10 +249,21 @@ class Connection : thisReq.getHeaderValue(boost::beast::http::field::upgrade), "websocket")) { - handler->handleUpgrade(thisReq, res, std::move(adaptor)); - // delete lambda with self shared_ptr - // to enable connection destruction - asyncResp->res.setCompleteRequestHandler(nullptr); + asyncResp->res.setCompleteRequestHandler( + [self(shared_from_this())](crow::Response& thisRes) { + if (thisRes.result() != boost::beast::http::status::ok) + { + // When any error occurs before handle upgradation, + // the result in response will be set to respective + // error. By default the Result will be OK (200), + // which implies successful handle upgrade. Response + // needs to be sent over this connection only on + // failure. + self->completeRequest(thisRes); + return; + } + }); + handler->handleUpgrade(thisReq, asyncResp, std::move(adaptor)); return; } std::string_view expected = diff --git a/http/routing.hpp b/http/routing.hpp index 5ebc11fbf4..a85bd3ae59 100644 --- a/http/routing.hpp +++ b/http/routing.hpp @@ -55,19 +55,20 @@ class BaseRule virtual void handle(const Request& /*req*/, const std::shared_ptr<bmcweb::AsyncResp>&, const RoutingParams&) = 0; - virtual void handleUpgrade(const Request& /*req*/, Response& res, - boost::asio::ip::tcp::socket&& /*adaptor*/) + virtual void + handleUpgrade(const Request& /*req*/, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + boost::asio::ip::tcp::socket&& /*adaptor*/) { - res.result(boost::beast::http::status::not_found); - res.end(); + asyncResp->res.result(boost::beast::http::status::not_found); } #ifdef BMCWEB_ENABLE_SSL virtual void handleUpgrade( - const Request& /*req*/, Response& res, + const Request& /*req*/, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&& /*adaptor*/) { - res.result(boost::beast::http::status::not_found); - res.end(); + asyncResp->res.result(boost::beast::http::status::not_found); } #endif @@ -345,7 +346,8 @@ class WebSocketRule : public BaseRule asyncResp->res.result(boost::beast::http::status::not_found); } - void handleUpgrade(const Request& req, Response& /*res*/, + void handleUpgrade(const Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/, boost::asio::ip::tcp::socket&& adaptor) override { BMCWEB_LOG_DEBUG << "Websocket handles upgrade"; @@ -358,7 +360,8 @@ class WebSocketRule : public BaseRule myConnection->start(); } #ifdef BMCWEB_ENABLE_SSL - void handleUpgrade(const Request& req, Response& /*res*/, + void handleUpgrade(const Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/, boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&& adaptor) override { @@ -1239,13 +1242,14 @@ class Router } template <typename Adaptor> - void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor) + void handleUpgrade(const Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + Adaptor&& adaptor) { std::optional<HttpVerb> verb = httpVerbFromBoost(req.method()); if (!verb || static_cast<size_t>(*verb) >= perMethods.size()) { - res.result(boost::beast::http::status::not_found); - res.end(); + asyncResp->res.result(boost::beast::http::status::not_found); return; } PerMethod& perMethod = perMethods[static_cast<size_t>(*verb)]; @@ -1259,8 +1263,7 @@ class Router { BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url().encoded_path(); - res.result(boost::beast::http::status::not_found); - res.end(); + asyncResp->res.result(boost::beast::http::status::not_found); return; } @@ -1277,8 +1280,7 @@ class Router << req.methodString() << "(" << static_cast<uint32_t>(*verb) << ") / " << rules[ruleIndex]->getMethods(); - res.result(boost::beast::http::status::not_found); - res.end(); + asyncResp->res.result(boost::beast::http::status::not_found); return; } @@ -1289,14 +1291,14 @@ class Router // any uncaught exceptions become 500s try { - rules[ruleIndex]->handleUpgrade(req, res, + rules[ruleIndex]->handleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor)); } catch (const std::exception& e) { BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what(); - res.result(boost::beast::http::status::internal_server_error); - res.end(); + asyncResp->res.result( + boost::beast::http::status::internal_server_error); return; } catch (...) @@ -1304,8 +1306,8 @@ class Router BMCWEB_LOG_ERROR << "An uncaught exception occurred. The type was unknown " "so no information was available."; - res.result(boost::beast::http::status::internal_server_error); - res.end(); + asyncResp->res.result( + boost::beast::http::status::internal_server_error); return; } } |