xref: /openbmc/bmcweb/http/http_response.hpp (revision 262d7d4b)
1 #pragma once
2 #include "http_request.hpp"
3 #include "logging.hpp"
4 #include "nlohmann/json.hpp"
5 
6 #include <boost/beast/http/message.hpp>
7 
8 #include <string>
9 
10 namespace crow
11 {
12 
13 template <typename Adaptor, typename Handler>
14 class Connection;
15 
16 struct Response
17 {
18     template <typename Adaptor, typename Handler>
19     friend class crow::Connection;
20     using response_type =
21         boost::beast::http::response<boost::beast::http::string_body>;
22 
23     std::optional<response_type> stringResponse;
24 
25     nlohmann::json jsonValue;
26 
27     void addHeader(const std::string_view key, const std::string_view value)
28     {
29         stringResponse->set(key, value);
30     }
31 
32     void addHeader(boost::beast::http::field key, std::string_view value)
33     {
34         stringResponse->set(key, value);
35     }
36 
37     Response() : stringResponse(response_type{})
38     {}
39 
40     Response& operator=(const Response& r) = delete;
41 
42     Response& operator=(Response&& r) noexcept
43     {
44         BMCWEB_LOG_DEBUG << "Moving response containers";
45         stringResponse = std::move(r.stringResponse);
46         r.stringResponse.emplace(response_type{});
47         jsonValue = std::move(r.jsonValue);
48         completed = r.completed;
49         return *this;
50     }
51 
52     void result(boost::beast::http::status v)
53     {
54         stringResponse->result(v);
55     }
56 
57     boost::beast::http::status result()
58     {
59         return stringResponse->result();
60     }
61 
62     unsigned resultInt()
63     {
64         return stringResponse->result_int();
65     }
66 
67     std::string_view reason()
68     {
69         return stringResponse->reason();
70     }
71 
72     bool isCompleted() const noexcept
73     {
74         return completed;
75     }
76 
77     std::string& body()
78     {
79         return stringResponse->body();
80     }
81 
82     void keepAlive(bool k)
83     {
84         stringResponse->keep_alive(k);
85     }
86 
87     bool keepAlive()
88     {
89         return stringResponse->keep_alive();
90     }
91 
92     void preparePayload()
93     {
94         stringResponse->prepare_payload();
95     }
96 
97     void clear()
98     {
99         BMCWEB_LOG_DEBUG << this << " Clearing response containers";
100         stringResponse.emplace(response_type{});
101         jsonValue.clear();
102         completed = false;
103     }
104 
105     void write(std::string_view bodyPart)
106     {
107         stringResponse->body() += std::string(bodyPart);
108     }
109 
110     void end()
111     {
112         if (completed)
113         {
114             BMCWEB_LOG_ERROR << "Response was ended twice";
115             return;
116         }
117         completed = true;
118         BMCWEB_LOG_DEBUG << "calling completion handler";
119         if (completeRequestHandler)
120         {
121             BMCWEB_LOG_DEBUG << "completion handler was valid";
122             completeRequestHandler();
123         }
124     }
125 
126     void end(std::string_view bodyPart)
127     {
128         write(bodyPart);
129         end();
130     }
131 
132     bool isAlive()
133     {
134         return isAliveHelper && isAliveHelper();
135     }
136 
137   private:
138     bool completed{};
139     std::function<void()> completeRequestHandler;
140     std::function<bool()> isAliveHelper;
141 
142     // In case of a JSON object, set the Content-Type header
143     void jsonMode()
144     {
145         addHeader("Content-Type", "application/json");
146     }
147 };
148 } // namespace crow
149