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