1 #pragma once 2 #include "logging.hpp" 3 #include "nlohmann/json.hpp" 4 5 #include <boost/beast/http/message.hpp> 6 #include <boost/beast/http/string_body.hpp> 7 8 #include <optional> 9 #include <string> 10 #include <string_view> 11 12 namespace crow 13 { 14 15 template <typename Adaptor, typename Handler> 16 class Connection; 17 18 struct Response 19 { 20 template <typename Adaptor, typename Handler> 21 friend class crow::Connection; 22 using response_type = 23 boost::beast::http::response<boost::beast::http::string_body>; 24 25 std::optional<response_type> stringResponse; 26 27 nlohmann::json jsonValue; 28 29 void addHeader(const std::string_view key, const std::string_view value) 30 { 31 stringResponse->set(key, value); 32 } 33 34 void addHeader(boost::beast::http::field key, std::string_view value) 35 { 36 stringResponse->set(key, value); 37 } 38 39 Response() : stringResponse(response_type{}) 40 {} 41 42 ~Response() = default; 43 44 Response(const Response&) = delete; 45 Response(Response&&) = delete; 46 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 73 std::string_view reason() 74 { 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 93 bool keepAlive() 94 { 95 return stringResponse->keep_alive(); 96 } 97 98 void preparePayload() 99 { 100 stringResponse->prepare_payload(); 101 } 102 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 111 void write(std::string_view bodyPart) 112 { 113 stringResponse->body() += std::string(bodyPart); 114 } 115 116 void end() 117 { 118 if (completed) 119 { 120 BMCWEB_LOG_ERROR << "Response was ended twice"; 121 return; 122 } 123 completed = true; 124 BMCWEB_LOG_DEBUG << "calling completion handler"; 125 if (completeRequestHandler) 126 { 127 BMCWEB_LOG_DEBUG << "completion handler was valid"; 128 completeRequestHandler(); 129 } 130 } 131 132 void end(std::string_view bodyPart) 133 { 134 write(bodyPart); 135 end(); 136 } 137 138 bool isAlive() 139 { 140 return isAliveHelper && isAliveHelper(); 141 } 142 143 void setCompleteRequestHandler(std::function<void()> newHandler) 144 { 145 completeRequestHandler = std::move(newHandler); 146 } 147 148 private: 149 bool completed{}; 150 std::function<void()> completeRequestHandler; 151 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 } 158 }; 159 } // namespace crow 160