diff options
author | Carson Labrado <clabrado@google.com> | 2022-04-05 19:03:20 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2022-05-17 19:49:24 +0300 |
commit | 039a47e3474d5667d295984f330e876aef309eac (patch) | |
tree | 7d953c4e6e4a596a393534077aca08f66239cdd0 /http | |
parent | 88a03c55257786d1c3e659b00531ffce071ea324 (diff) | |
download | bmcweb-039a47e3474d5667d295984f330e876aef309eac.tar.xz |
Add callback for response handling to HttpClient
Adds sendDataWithCallback() which allows the caller to include a
callback specifying how to handle the response to that
request. This will be utilized for Redfish Aggregation
including returning the responses received when forwarding
requests to satellite BMCs.
Change-Id: I93826c8b254a5f28a982295d4145453352a90fae
Signed-off-by: Carson Labrado <clabrado@google.com>
Diffstat (limited to 'http')
-rw-r--r-- | http/http_client.hpp | 66 | ||||
-rw-r--r-- | http/http_response.hpp | 2 |
2 files changed, 56 insertions, 12 deletions
diff --git a/http/http_client.hpp b/http/http_client.hpp index 16378232cb..a672447506 100644 --- a/http/http_client.hpp +++ b/http/http_client.hpp @@ -73,11 +73,12 @@ struct RetryPolicyData struct PendingRequest { std::string requestData; - std::function<void(bool, uint32_t)> callback; + std::function<void(bool, uint32_t, Response&)> callback; RetryPolicyData retryPolicy; - PendingRequest(const std::string& requestData, - const std::function<void(bool, uint32_t)>& callback, - const RetryPolicyData& retryPolicy) : + PendingRequest( + const std::string& requestData, + const std::function<void(bool, uint32_t, Response&)>& callback, + const RetryPolicyData& retryPolicy) : requestData(requestData), callback(callback), retryPolicy(retryPolicy) {} @@ -105,9 +106,10 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo> boost::beast::http::response_parser<boost::beast::http::string_body>> parser; boost::beast::flat_static_buffer<httpReadBodyLimit> buffer; + Response res; // Ascync callables - std::function<void(bool, uint32_t)> callback; + std::function<void(bool, uint32_t, Response&)> callback; crow::async_resolve::Resolver resolver; boost::beast::tcp_stream conn; boost::asio::steady_timer timer; @@ -258,7 +260,12 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo> BMCWEB_LOG_DEBUG << "recvMessage() keepalive : " << self->parser->keep_alive(); - self->callback(self->parser->keep_alive(), self->connId); + // Copy the response into a Response object so that it can be + // processed by the callback function. + self->res.clear(); + self->res.stringResponse = self->parser->release(); + self->callback(self->parser->keep_alive(), self->connId, + self->res); }); } @@ -269,16 +276,22 @@ class ConnectionInfo : public std::enable_shared_from_this<ConnectionInfo> BMCWEB_LOG_ERROR << "Maximum number of retries reached."; BMCWEB_LOG_DEBUG << "Retry policy: " << retryPolicy.retryPolicyAction; + + // We want to return a 502 to indicate there was an error with the + // external server + res.clear(); + redfish::messages::operationFailed(res); + if (retryPolicy.retryPolicyAction == "TerminateAfterRetries") { // TODO: delete subscription state = ConnState::terminated; - callback(false, connId); + callback(false, connId, res); } if (retryPolicy.retryPolicyAction == "SuspendRetries") { state = ConnState::suspended; - callback(false, connId); + callback(false, connId, res); } // Reset the retrycount to zero so that client can try connecting // again if needed @@ -483,12 +496,18 @@ class ConnectionPool : public std::enable_shared_from_this<ConnectionPool> } } - void sendData(std::string& data, const RetryPolicyData& retryPolicy) + void sendData(std::string& data, const RetryPolicyData& retryPolicy, + std::function<void(Response&)>& resHandler) { std::weak_ptr<ConnectionPool> weakSelf = weak_from_this(); // Callback to be called once the request has been sent - auto cb = [weakSelf](bool keepAlive, uint32_t connId) { + auto cb = [weakSelf, resHandler](bool keepAlive, uint32_t connId, + Response& res) { + // Allow provided callback to perform additional processing of the + // request + resHandler(res); + // If requests remain in the queue then we want to reuse this // connection to send the next request std::shared_ptr<ConnectionPool> self = weakSelf.lock(); @@ -600,6 +619,14 @@ class HttpClient std::unordered_map<std::string, RetryPolicyData> retryInfo; HttpClient() = default; + // Used as a dummy callback by sendData() in order to call + // sendDataWithCallback() + static void genericResHandler(Response& res) + { + BMCWEB_LOG_DEBUG << "Response handled with return code: " + << std::to_string(res.resultInt()); + }; + public: HttpClient(const HttpClient&) = delete; HttpClient& operator=(const HttpClient&) = delete; @@ -613,12 +640,29 @@ class HttpClient return handler; } + // Send a request to destIP:destPort where additional processing of the + // result is not required void sendData(std::string& data, const std::string& id, const std::string& destIP, const uint16_t destPort, const std::string& destUri, const boost::beast::http::fields& httpHeader, std::string& retryPolicyName) { + std::function<void(Response&)> cb = genericResHandler; + sendDataWithCallback(data, id, destIP, destPort, destUri, httpHeader, + retryPolicyName, cb); + } + + // Send request to destIP:destPort and use the provided callback to + // handle the response + void sendDataWithCallback(std::string& data, const std::string& id, + const std::string& destIP, + const uint16_t destPort, + const std::string& destUri, + const boost::beast::http::fields& httpHeader, + std::string& retryPolicyName, + std::function<void(Response&)>& resHandler) + { std::string clientKey = destIP + ":" + std::to_string(destPort); // Use nullptr to avoid creating a ConnectionPool each time auto result = connectionPools.try_emplace(clientKey, nullptr); @@ -647,7 +691,7 @@ class HttpClient // Send the data using either the existing connection pool or the newly // created connection pool - result.first->second->sendData(data, policy.first->second); + result.first->second->sendData(data, policy.first->second, resHandler); } void setRetryConfig(const uint32_t retryAttempts, diff --git a/http/http_response.hpp b/http/http_response.hpp index 58a802915b..6c842d742c 100644 --- a/http/http_response.hpp +++ b/http/http_response.hpp @@ -76,7 +76,7 @@ struct Response return stringResponse->result(); } - unsigned resultInt() + unsigned resultInt() const { return stringResponse->result_int(); } |