blob: 1deae34fbbf8f797a074015887a23886e0b0e0ab [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
Ed Tanous1abe55e2018-09-05 08:30:59 -07002#include "nlohmann/json.hpp"
3
4#include <boost/beast/http.hpp>
Ed Tanous7045c8d2017-04-03 10:04:37 -07005#include <string>
Ed Tanous7045c8d2017-04-03 10:04:37 -07006
Ed Tanous7045c8d2017-04-03 10:04:37 -07007#include "crow/http_request.h"
Ed Tanous0d485ef2017-05-23 09:23:53 -07008#include "crow/logging.h"
Ed Tanous7045c8d2017-04-03 10:04:37 -07009
Ed Tanous1abe55e2018-09-05 08:30:59 -070010namespace crow
11{
Ed Tanouse0d918b2018-03-27 17:41:04 -070012
Ed Tanous7045c8d2017-04-03 10:04:37 -070013template <typename Adaptor, typename Handler, typename... Middlewares>
14class Connection;
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +010015
Ed Tanous1abe55e2018-09-05 08:30:59 -070016struct Response
17{
18 template <typename Adaptor, typename Handler, typename... Middlewares>
19 friend class crow::Connection;
20 using response_type =
21 boost::beast::http::response<boost::beast::http::string_body>;
Ed Tanous7045c8d2017-04-03 10:04:37 -070022
Ed Tanousa24526d2018-12-10 15:17:59 -080023 std::optional<response_type> stringResponse;
Ed Tanouse0d918b2018-03-27 17:41:04 -070024
Ed Tanous1abe55e2018-09-05 08:30:59 -070025 nlohmann::json jsonValue;
Ed Tanous7045c8d2017-04-03 10:04:37 -070026
Ed Tanous1abe55e2018-09-05 08:30:59 -070027 void addHeader(const boost::string_view key, const boost::string_view value)
28 {
29 stringResponse->set(key, value);
Ed Tanous7045c8d2017-04-03 10:04:37 -070030 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070031
32 void addHeader(boost::beast::http::field key, boost::string_view value)
33 {
34 stringResponse->set(key, value);
Ed Tanous2cd4cc12018-07-25 10:51:19 -070035 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070036
Ed Tanous1abe55e2018-09-05 08:30:59 -070037 Response() : stringResponse(response_type{})
38 {
39 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070040
Ed Tanous1abe55e2018-09-05 08:30:59 -070041 explicit Response(boost::beast::http::status code) :
42 stringResponse(response_type{})
43 {
44 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070045
Ed Tanous1abe55e2018-09-05 08:30:59 -070046 explicit Response(boost::string_view body_) :
47 stringResponse(response_type{})
48 {
49 stringResponse->body() = std::string(body_);
50 }
Ed Tanous7045c8d2017-04-03 10:04:37 -070051
Ed Tanous1abe55e2018-09-05 08:30:59 -070052 Response(boost::beast::http::status code, boost::string_view s) :
53 stringResponse(response_type{})
54 {
55 stringResponse->result(code);
56 stringResponse->body() = std::string(s);
57 }
58
59 Response(Response&& r)
60 {
61 BMCWEB_LOG_DEBUG << "Moving response containers";
62 *this = std::move(r);
63 }
64
65 ~Response()
66 {
67 BMCWEB_LOG_DEBUG << this << " Destroying response";
68 }
69
70 Response& operator=(const Response& r) = delete;
71
72 Response& operator=(Response&& r) noexcept
73 {
74 BMCWEB_LOG_DEBUG << "Moving response containers";
75 stringResponse = std::move(r.stringResponse);
76 r.stringResponse.emplace(response_type{});
77 jsonValue = std::move(r.jsonValue);
78 completed = r.completed;
79 return *this;
80 }
81
82 void result(boost::beast::http::status v)
83 {
84 stringResponse->result(v);
85 }
86
87 boost::beast::http::status result()
88 {
89 return stringResponse->result();
90 }
91
92 unsigned resultInt()
93 {
94 return stringResponse->result_int();
95 }
96
97 boost::string_view reason()
98 {
99 return stringResponse->reason();
100 }
101
102 bool isCompleted() const noexcept
103 {
104 return completed;
105 }
106
107 std::string& body()
108 {
109 return stringResponse->body();
110 }
111
112 void keepAlive(bool k)
113 {
114 stringResponse->keep_alive(k);
115 }
116
Ed Tanousceac6f72018-12-02 11:58:47 -0800117 bool keepAlive()
118 {
119 return stringResponse->keep_alive();
120 }
121
Ed Tanous1abe55e2018-09-05 08:30:59 -0700122 void preparePayload()
123 {
124 stringResponse->prepare_payload();
125 };
126
127 void clear()
128 {
129 BMCWEB_LOG_DEBUG << this << " Clearing response containers";
130 stringResponse.emplace(response_type{});
131 jsonValue.clear();
132 completed = false;
133 }
134
135 void write(boost::string_view body_part)
136 {
137 stringResponse->body() += std::string(body_part);
138 }
139
140 void end()
141 {
142 if (completed)
143 {
144 BMCWEB_LOG_ERROR << "Response was ended twice";
145 return;
146 }
147 completed = true;
148 BMCWEB_LOG_DEBUG << "calling completion handler";
149 if (completeRequestHandler)
150 {
151 BMCWEB_LOG_DEBUG << "completion handler was valid";
152 completeRequestHandler();
153 }
154 }
155
156 void end(boost::string_view body_part)
157 {
158 write(body_part);
159 end();
160 }
161
162 bool isAlive()
163 {
164 return isAliveHelper && isAliveHelper();
165 }
166
167 private:
168 bool completed{};
169 std::function<void()> completeRequestHandler;
170 std::function<bool()> isAliveHelper;
171
172 // In case of a JSON object, set the Content-Type header
173 void jsonMode()
174 {
175 addHeader("Content-Type", "application/json");
176 }
Ed Tanous7045c8d2017-04-03 10:04:37 -0700177};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700178} // namespace crow