xref: /openbmc/bmcweb/http/http_response.hpp (revision 8a9a25c821f40b9cd2d94a483581c435e4e4a27e)
104e438cbSEd Tanous #pragma once
204e438cbSEd Tanous #include "logging.hpp"
304e438cbSEd Tanous #include "nlohmann/json.hpp"
404e438cbSEd Tanous 
504e438cbSEd Tanous #include <boost/beast/http/message.hpp>
6d4b6c660SEd Tanous #include <boost/beast/http/string_body.hpp>
704e438cbSEd Tanous 
8*8a9a25c8SEd Tanous #include <optional>
904e438cbSEd Tanous #include <string>
10*8a9a25c8SEd Tanous #include <string_view>
1104e438cbSEd Tanous 
1204e438cbSEd Tanous namespace crow
1304e438cbSEd Tanous {
1404e438cbSEd Tanous 
1504e438cbSEd Tanous template <typename Adaptor, typename Handler>
1604e438cbSEd Tanous class Connection;
1704e438cbSEd Tanous 
1804e438cbSEd Tanous struct Response
1904e438cbSEd Tanous {
2004e438cbSEd Tanous     template <typename Adaptor, typename Handler>
2104e438cbSEd Tanous     friend class crow::Connection;
2204e438cbSEd Tanous     using response_type =
2304e438cbSEd Tanous         boost::beast::http::response<boost::beast::http::string_body>;
2404e438cbSEd Tanous 
2504e438cbSEd Tanous     std::optional<response_type> stringResponse;
2604e438cbSEd Tanous 
2704e438cbSEd Tanous     nlohmann::json jsonValue;
2804e438cbSEd Tanous 
2904e438cbSEd Tanous     void addHeader(const std::string_view key, const std::string_view value)
3004e438cbSEd Tanous     {
3104e438cbSEd Tanous         stringResponse->set(key, value);
3204e438cbSEd Tanous     }
3304e438cbSEd Tanous 
3404e438cbSEd Tanous     void addHeader(boost::beast::http::field key, std::string_view value)
3504e438cbSEd Tanous     {
3604e438cbSEd Tanous         stringResponse->set(key, value);
3704e438cbSEd Tanous     }
3804e438cbSEd Tanous 
3904e438cbSEd Tanous     Response() : stringResponse(response_type{})
4004e438cbSEd Tanous     {}
4104e438cbSEd Tanous 
4204e438cbSEd Tanous     Response& operator=(const Response& r) = delete;
4304e438cbSEd Tanous 
4404e438cbSEd Tanous     Response& operator=(Response&& r) noexcept
4504e438cbSEd Tanous     {
4604e438cbSEd Tanous         BMCWEB_LOG_DEBUG << "Moving response containers";
4704e438cbSEd Tanous         stringResponse = std::move(r.stringResponse);
4804e438cbSEd Tanous         r.stringResponse.emplace(response_type{});
4904e438cbSEd Tanous         jsonValue = std::move(r.jsonValue);
5004e438cbSEd Tanous         completed = r.completed;
5104e438cbSEd Tanous         return *this;
5204e438cbSEd Tanous     }
5304e438cbSEd Tanous 
5404e438cbSEd Tanous     void result(boost::beast::http::status v)
5504e438cbSEd Tanous     {
5604e438cbSEd Tanous         stringResponse->result(v);
5704e438cbSEd Tanous     }
5804e438cbSEd Tanous 
5904e438cbSEd Tanous     boost::beast::http::status result()
6004e438cbSEd Tanous     {
6104e438cbSEd Tanous         return stringResponse->result();
6204e438cbSEd Tanous     }
6304e438cbSEd Tanous 
6404e438cbSEd Tanous     unsigned resultInt()
6504e438cbSEd Tanous     {
6604e438cbSEd Tanous         return stringResponse->result_int();
6704e438cbSEd Tanous     }
6804e438cbSEd Tanous 
6904e438cbSEd Tanous     std::string_view reason()
7004e438cbSEd Tanous     {
7104e438cbSEd Tanous         return stringResponse->reason();
7204e438cbSEd Tanous     }
7304e438cbSEd Tanous 
7404e438cbSEd Tanous     bool isCompleted() const noexcept
7504e438cbSEd Tanous     {
7604e438cbSEd Tanous         return completed;
7704e438cbSEd Tanous     }
7804e438cbSEd Tanous 
7904e438cbSEd Tanous     std::string& body()
8004e438cbSEd Tanous     {
8104e438cbSEd Tanous         return stringResponse->body();
8204e438cbSEd Tanous     }
8304e438cbSEd Tanous 
8404e438cbSEd Tanous     void keepAlive(bool k)
8504e438cbSEd Tanous     {
8604e438cbSEd Tanous         stringResponse->keep_alive(k);
8704e438cbSEd Tanous     }
8804e438cbSEd Tanous 
8904e438cbSEd Tanous     bool keepAlive()
9004e438cbSEd Tanous     {
9104e438cbSEd Tanous         return stringResponse->keep_alive();
9204e438cbSEd Tanous     }
9304e438cbSEd Tanous 
9404e438cbSEd Tanous     void preparePayload()
9504e438cbSEd Tanous     {
9604e438cbSEd Tanous         stringResponse->prepare_payload();
9704e438cbSEd Tanous     }
9804e438cbSEd Tanous 
9904e438cbSEd Tanous     void clear()
10004e438cbSEd Tanous     {
10104e438cbSEd Tanous         BMCWEB_LOG_DEBUG << this << " Clearing response containers";
10204e438cbSEd Tanous         stringResponse.emplace(response_type{});
10304e438cbSEd Tanous         jsonValue.clear();
10404e438cbSEd Tanous         completed = false;
10504e438cbSEd Tanous     }
10604e438cbSEd Tanous 
10781ce609eSEd Tanous     void write(std::string_view bodyPart)
10804e438cbSEd Tanous     {
10981ce609eSEd Tanous         stringResponse->body() += std::string(bodyPart);
11004e438cbSEd Tanous     }
11104e438cbSEd Tanous 
11204e438cbSEd Tanous     void end()
11304e438cbSEd Tanous     {
11404e438cbSEd Tanous         if (completed)
11504e438cbSEd Tanous         {
11604e438cbSEd Tanous             BMCWEB_LOG_ERROR << "Response was ended twice";
11704e438cbSEd Tanous             return;
11804e438cbSEd Tanous         }
11904e438cbSEd Tanous         completed = true;
12004e438cbSEd Tanous         BMCWEB_LOG_DEBUG << "calling completion handler";
12104e438cbSEd Tanous         if (completeRequestHandler)
12204e438cbSEd Tanous         {
12304e438cbSEd Tanous             BMCWEB_LOG_DEBUG << "completion handler was valid";
12404e438cbSEd Tanous             completeRequestHandler();
12504e438cbSEd Tanous         }
12604e438cbSEd Tanous     }
12704e438cbSEd Tanous 
12881ce609eSEd Tanous     void end(std::string_view bodyPart)
12904e438cbSEd Tanous     {
13081ce609eSEd Tanous         write(bodyPart);
13104e438cbSEd Tanous         end();
13204e438cbSEd Tanous     }
13304e438cbSEd Tanous 
13404e438cbSEd Tanous     bool isAlive()
13504e438cbSEd Tanous     {
13604e438cbSEd Tanous         return isAliveHelper && isAliveHelper();
13704e438cbSEd Tanous     }
13804e438cbSEd Tanous 
13904e438cbSEd Tanous   private:
14004e438cbSEd Tanous     bool completed{};
14104e438cbSEd Tanous     std::function<void()> completeRequestHandler;
14204e438cbSEd Tanous     std::function<bool()> isAliveHelper;
14304e438cbSEd Tanous 
14404e438cbSEd Tanous     // In case of a JSON object, set the Content-Type header
14504e438cbSEd Tanous     void jsonMode()
14604e438cbSEd Tanous     {
14704e438cbSEd Tanous         addHeader("Content-Type", "application/json");
14804e438cbSEd Tanous     }
14904e438cbSEd Tanous };
15004e438cbSEd Tanous } // namespace crow
151