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& operator=(const Response& r) = delete; 43 44 Response& operator=(Response&& r) noexcept 45 { 46 BMCWEB_LOG_DEBUG << "Moving response containers"; 47 stringResponse = std::move(r.stringResponse); 48 r.stringResponse.emplace(response_type{}); 49 jsonValue = std::move(r.jsonValue); 50 completed = r.completed; 51 return *this; 52 } 53 54 void result(boost::beast::http::status v) 55 { 56 stringResponse->result(v); 57 } 58 59 boost::beast::http::status result() 60 { 61 return stringResponse->result(); 62 } 63 64 unsigned resultInt() 65 { 66 return stringResponse->result_int(); 67 } 68 69 std::string_view reason() 70 { 71 return stringResponse->reason(); 72 } 73 74 bool isCompleted() const noexcept 75 { 76 return completed; 77 } 78 79 std::string& body() 80 { 81 return stringResponse->body(); 82 } 83 84 void keepAlive(bool k) 85 { 86 stringResponse->keep_alive(k); 87 } 88 89 bool keepAlive() 90 { 91 return stringResponse->keep_alive(); 92 } 93 94 void preparePayload() 95 { 96 stringResponse->prepare_payload(); 97 } 98 99 void clear() 100 { 101 BMCWEB_LOG_DEBUG << this << " Clearing response containers"; 102 stringResponse.emplace(response_type{}); 103 jsonValue.clear(); 104 completed = false; 105 } 106 107 void write(std::string_view bodyPart) 108 { 109 stringResponse->body() += std::string(bodyPart); 110 } 111 112 void end() 113 { 114 if (completed) 115 { 116 BMCWEB_LOG_ERROR << "Response was ended twice"; 117 return; 118 } 119 completed = true; 120 BMCWEB_LOG_DEBUG << "calling completion handler"; 121 if (completeRequestHandler) 122 { 123 BMCWEB_LOG_DEBUG << "completion handler was valid"; 124 completeRequestHandler(); 125 } 126 } 127 128 void end(std::string_view bodyPart) 129 { 130 write(bodyPart); 131 end(); 132 } 133 134 bool isAlive() 135 { 136 return isAliveHelper && isAliveHelper(); 137 } 138 139 private: 140 bool completed{}; 141 std::function<void()> completeRequestHandler; 142 std::function<bool()> isAliveHelper; 143 144 // In case of a JSON object, set the Content-Type header 145 void jsonMode() 146 { 147 addHeader("Content-Type", "application/json"); 148 } 149 }; 150 } // namespace crow 151