blob: c99b2c378bd403bf50c62e4612cb956ce0089139 [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
Ed Tanous04e438c2020-10-03 08:06:26 -07002#include "logging.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -07003#include "nlohmann/json.hpp"
4
Ed Tanousd43cd0c2020-09-30 20:46:53 -07005#include <boost/beast/http/message.hpp>
Ed Tanousd4b6c662021-03-10 13:29:30 -08006#include <boost/beast/http/string_body.hpp>
Ed Tanous7045c8d2017-04-03 10:04:37 -07007
Ed Tanous8a9a25c2021-05-11 14:50:58 -07008#include <optional>
Gunnar Mills1214b7e2020-06-04 10:11:30 -05009#include <string>
Ed Tanous8a9a25c2021-05-11 14:50:58 -070010#include <string_view>
Ed Tanous7045c8d2017-04-03 10:04:37 -070011
Ed Tanous1abe55e2018-09-05 08:30:59 -070012namespace crow
13{
Ed Tanouse0d918b2018-03-27 17:41:04 -070014
Ed Tanous52cc1122020-07-18 13:51:21 -070015template <typename Adaptor, typename Handler>
Ed Tanous7045c8d2017-04-03 10:04:37 -070016class Connection;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +010017
Ed Tanous1abe55e2018-09-05 08:30:59 -070018struct Response
19{
Ed Tanous52cc1122020-07-18 13:51:21 -070020 template <typename Adaptor, typename Handler>
Ed Tanous1abe55e2018-09-05 08:30:59 -070021 friend class crow::Connection;
22 using response_type =
23 boost::beast::http::response<boost::beast::http::string_body>;
Ed Tanous7045c8d2017-04-03 10:04:37 -070024
Ed Tanousa24526d2018-12-10 15:17:59 -080025 std::optional<response_type> stringResponse;
Ed Tanouse0d918b2018-03-27 17:41:04 -070026
Ed Tanous1abe55e2018-09-05 08:30:59 -070027 nlohmann::json jsonValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -070028
Ed Tanous39e77502019-03-04 17:35:53 -080029 void addHeader(const std::string_view key, const std::string_view value)
Ed Tanous1abe55e2018-09-05 08:30:59 -070030 {
31 stringResponse->set(key, value);
Ed Tanous7045c8d2017-04-03 10:04:37 -070032 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070033
Ed Tanous39e77502019-03-04 17:35:53 -080034 void addHeader(boost::beast::http::field key, std::string_view value)
Ed Tanous1abe55e2018-09-05 08:30:59 -070035 {
36 stringResponse->set(key, value);
Ed Tanous2cd4cc12018-07-25 10:51:19 -070037 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070038
Ed Tanous1abe55e2018-09-05 08:30:59 -070039 Response() : stringResponse(response_type{})
Gunnar Mills1214b7e2020-06-04 10:11:30 -050040 {}
Ed Tanous7045c8d2017-04-03 10:04:37 -070041
zhanghch0591995f32021-10-20 18:43:55 +080042 Response(Response&& res) = delete;
43
Ed Tanous1abe55e2018-09-05 08:30:59 -070044 Response& operator=(const Response& r) = delete;
45
46 Response& operator=(Response&& r) noexcept
47 {
48 BMCWEB_LOG_DEBUG << "Moving response containers";
49 stringResponse = std::move(r.stringResponse);
50 r.stringResponse.emplace(response_type{});
51 jsonValue = std::move(r.jsonValue);
52 completed = r.completed;
53 return *this;
54 }
55
56 void result(boost::beast::http::status v)
57 {
58 stringResponse->result(v);
59 }
60
61 boost::beast::http::status result()
62 {
63 return stringResponse->result();
64 }
65
66 unsigned resultInt()
67 {
68 return stringResponse->result_int();
69 }
70
Ed Tanous39e77502019-03-04 17:35:53 -080071 std::string_view reason()
Ed Tanous1abe55e2018-09-05 08:30:59 -070072 {
73 return stringResponse->reason();
74 }
75
76 bool isCompleted() const noexcept
77 {
78 return completed;
79 }
80
81 std::string& body()
82 {
83 return stringResponse->body();
84 }
85
86 void keepAlive(bool k)
87 {
88 stringResponse->keep_alive(k);
89 }
90
Ed Tanousceac6f72018-12-02 11:58:47 -080091 bool keepAlive()
92 {
93 return stringResponse->keep_alive();
94 }
95
Ed Tanous1abe55e2018-09-05 08:30:59 -070096 void preparePayload()
97 {
98 stringResponse->prepare_payload();
Ed Tanous23a21a12020-07-25 04:45:05 +000099 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700100
101 void clear()
102 {
103 BMCWEB_LOG_DEBUG << this << " Clearing response containers";
104 stringResponse.emplace(response_type{});
105 jsonValue.clear();
106 completed = false;
107 }
108
Ed Tanous81ce6092020-12-17 16:54:55 +0000109 void write(std::string_view bodyPart)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700110 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000111 stringResponse->body() += std::string(bodyPart);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700112 }
113
114 void end()
115 {
116 if (completed)
117 {
zhanghch0591995f32021-10-20 18:43:55 +0800118 BMCWEB_LOG_ERROR << this << " Response was ended twice";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700119 return;
120 }
121 completed = true;
zhanghch0591995f32021-10-20 18:43:55 +0800122 BMCWEB_LOG_DEBUG << this << " calling completion handler";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700123 if (completeRequestHandler)
124 {
zhanghch0591995f32021-10-20 18:43:55 +0800125 BMCWEB_LOG_DEBUG << this << " completion handler was valid";
126 completeRequestHandler(*this);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700127 }
128 }
129
Ed Tanous1abe55e2018-09-05 08:30:59 -0700130 bool isAlive()
131 {
132 return isAliveHelper && isAliveHelper();
133 }
134
zhanghch0591995f32021-10-20 18:43:55 +0800135 void setCompleteRequestHandler(std::function<void(Response&)>&& handler)
John Edward Broadbent4147b8a2021-07-19 16:52:24 -0700136 {
zhanghch0591995f32021-10-20 18:43:55 +0800137 BMCWEB_LOG_DEBUG << this << " setting completion handler";
138 completeRequestHandler = std::move(handler);
139 }
140
141 std::function<void(Response&)> releaseCompleteRequestHandler()
142 {
143 BMCWEB_LOG_DEBUG << this << " releasing completion handler"
144 << static_cast<bool>(completeRequestHandler);
145 std::function<void(Response&)> ret = completeRequestHandler;
146 completeRequestHandler = nullptr;
147 return ret;
148 }
149
150 void setIsAliveHelper(std::function<bool()>&& handler)
151 {
152 isAliveHelper = std::move(handler);
153 }
154
155 std::function<bool()> releaseIsAliveHelper()
156 {
157 std::function<bool()> ret = std::move(isAliveHelper);
158 isAliveHelper = nullptr;
159 return ret;
John Edward Broadbent4147b8a2021-07-19 16:52:24 -0700160 }
161
Ed Tanous1abe55e2018-09-05 08:30:59 -0700162 private:
zhanghch0591995f32021-10-20 18:43:55 +0800163 bool completed = false;
164 std::function<void(Response&)> completeRequestHandler;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700165 std::function<bool()> isAliveHelper;
166
167 // In case of a JSON object, set the Content-Type header
168 void jsonMode()
169 {
170 addHeader("Content-Type", "application/json");
171 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700172};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700173} // namespace crow