blob: 08b76f247842297745296a5c452052d6749e3066 [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
Ed Tanousecd6a3a2022-01-07 09:18:40 -080042 ~Response() = default;
43
44 Response(const Response&) = delete;
45 Response(Response&&) = delete;
Ed Tanous1abe55e2018-09-05 08:30:59 -070046 Response& operator=(const Response& r) = delete;
47
48 Response& operator=(Response&& r) noexcept
49 {
50 BMCWEB_LOG_DEBUG << "Moving response containers";
51 stringResponse = std::move(r.stringResponse);
52 r.stringResponse.emplace(response_type{});
53 jsonValue = std::move(r.jsonValue);
54 completed = r.completed;
55 return *this;
56 }
57
58 void result(boost::beast::http::status v)
59 {
60 stringResponse->result(v);
61 }
62
63 boost::beast::http::status result()
64 {
65 return stringResponse->result();
66 }
67
68 unsigned resultInt()
69 {
70 return stringResponse->result_int();
71 }
72
Ed Tanous39e77502019-03-04 17:35:53 -080073 std::string_view reason()
Ed Tanous1abe55e2018-09-05 08:30:59 -070074 {
75 return stringResponse->reason();
76 }
77
78 bool isCompleted() const noexcept
79 {
80 return completed;
81 }
82
83 std::string& body()
84 {
85 return stringResponse->body();
86 }
87
88 void keepAlive(bool k)
89 {
90 stringResponse->keep_alive(k);
91 }
92
Ed Tanousceac6f72018-12-02 11:58:47 -080093 bool keepAlive()
94 {
95 return stringResponse->keep_alive();
96 }
97
Ed Tanous1abe55e2018-09-05 08:30:59 -070098 void preparePayload()
99 {
100 stringResponse->prepare_payload();
Ed Tanous23a21a12020-07-25 04:45:05 +0000101 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700102
103 void clear()
104 {
105 BMCWEB_LOG_DEBUG << this << " Clearing response containers";
106 stringResponse.emplace(response_type{});
107 jsonValue.clear();
108 completed = false;
109 }
110
Ed Tanous81ce6092020-12-17 16:54:55 +0000111 void write(std::string_view bodyPart)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700112 {
Ed Tanous81ce6092020-12-17 16:54:55 +0000113 stringResponse->body() += std::string(bodyPart);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700114 }
115
116 void end()
117 {
118 if (completed)
119 {
Gunnar Mills9062d472021-11-16 11:37:47 -0600120 BMCWEB_LOG_ERROR << "Response was ended twice";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700121 return;
122 }
123 completed = true;
Gunnar Mills9062d472021-11-16 11:37:47 -0600124 BMCWEB_LOG_DEBUG << "calling completion handler";
Ed Tanous1abe55e2018-09-05 08:30:59 -0700125 if (completeRequestHandler)
126 {
Gunnar Mills9062d472021-11-16 11:37:47 -0600127 BMCWEB_LOG_DEBUG << "completion handler was valid";
128 completeRequestHandler();
Ed Tanous1abe55e2018-09-05 08:30:59 -0700129 }
130 }
131
Gunnar Mills9062d472021-11-16 11:37:47 -0600132 void end(std::string_view bodyPart)
133 {
134 write(bodyPart);
135 end();
136 }
137
Ed Tanous1abe55e2018-09-05 08:30:59 -0700138 bool isAlive()
139 {
140 return isAliveHelper && isAliveHelper();
141 }
142
Gunnar Mills9062d472021-11-16 11:37:47 -0600143 void setCompleteRequestHandler(std::function<void()> newHandler)
John Edward Broadbent4147b8a2021-07-19 16:52:24 -0700144 {
Gunnar Mills9062d472021-11-16 11:37:47 -0600145 completeRequestHandler = std::move(newHandler);
John Edward Broadbent4147b8a2021-07-19 16:52:24 -0700146 }
147
Ed Tanous1abe55e2018-09-05 08:30:59 -0700148 private:
Gunnar Mills9062d472021-11-16 11:37:47 -0600149 bool completed{};
150 std::function<void()> completeRequestHandler;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700151 std::function<bool()> isAliveHelper;
152
153 // In case of a JSON object, set the Content-Type header
154 void jsonMode()
155 {
156 addHeader("Content-Type", "application/json");
157 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700158};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700159} // namespace crow