1 #pragma once 2 #include "http_request.hpp" 3 #include "logging.hpp" 4 #include "nlohmann/json.hpp" 5 6 #include <boost/beast/http/message.hpp> 7 8 #include <string> 9 10 namespace crow 11 { 12 13 template <typename Adaptor, typename Handler> 14 class Connection; 15 16 struct Response 17 { 18 template <typename Adaptor, typename Handler> 19 friend class crow::Connection; 20 using response_type = 21 boost::beast::http::response<boost::beast::http::string_body>; 22 23 std::optional<response_type> stringResponse; 24 25 nlohmann::json jsonValue; 26 27 void addHeader(const std::string_view key, const std::string_view value) 28 { 29 stringResponse->set(key, value); 30 } 31 32 void addHeader(boost::beast::http::field key, std::string_view value) 33 { 34 stringResponse->set(key, value); 35 } 36 37 Response() : stringResponse(response_type{}) 38 {} 39 40 Response& operator=(const Response& r) = delete; 41 42 Response& operator=(Response&& r) noexcept 43 { 44 BMCWEB_LOG_DEBUG << "Moving response containers"; 45 stringResponse = std::move(r.stringResponse); 46 r.stringResponse.emplace(response_type{}); 47 jsonValue = std::move(r.jsonValue); 48 completed = r.completed; 49 return *this; 50 } 51 52 void result(boost::beast::http::status v) 53 { 54 stringResponse->result(v); 55 } 56 57 boost::beast::http::status result() 58 { 59 return stringResponse->result(); 60 } 61 62 unsigned resultInt() 63 { 64 return stringResponse->result_int(); 65 } 66 67 std::string_view reason() 68 { 69 return stringResponse->reason(); 70 } 71 72 bool isCompleted() const noexcept 73 { 74 return completed; 75 } 76 77 std::string& body() 78 { 79 return stringResponse->body(); 80 } 81 82 void keepAlive(bool k) 83 { 84 stringResponse->keep_alive(k); 85 } 86 87 bool keepAlive() 88 { 89 return stringResponse->keep_alive(); 90 } 91 92 void preparePayload() 93 { 94 stringResponse->prepare_payload(); 95 } 96 97 void clear() 98 { 99 BMCWEB_LOG_DEBUG << this << " Clearing response containers"; 100 stringResponse.emplace(response_type{}); 101 jsonValue.clear(); 102 completed = false; 103 } 104 105 void write(std::string_view bodyPart) 106 { 107 stringResponse->body() += std::string(bodyPart); 108 } 109 110 void end() 111 { 112 if (completed) 113 { 114 BMCWEB_LOG_ERROR << "Response was ended twice"; 115 return; 116 } 117 completed = true; 118 BMCWEB_LOG_DEBUG << "calling completion handler"; 119 if (completeRequestHandler) 120 { 121 BMCWEB_LOG_DEBUG << "completion handler was valid"; 122 completeRequestHandler(); 123 } 124 } 125 126 void end(std::string_view bodyPart) 127 { 128 write(bodyPart); 129 end(); 130 } 131 132 bool isAlive() 133 { 134 return isAliveHelper && isAliveHelper(); 135 } 136 137 private: 138 bool completed{}; 139 std::function<void()> completeRequestHandler; 140 std::function<bool()> isAliveHelper; 141 142 // In case of a JSON object, set the Content-Type header 143 void jsonMode() 144 { 145 addHeader("Content-Type", "application/json"); 146 } 147 }; 148 } // namespace crow 149