#pragma once #include #include #include #include using std::string_view; struct HttpResponse { int status = 200; std::string body; std::string content_type = "text/plain"; std::unordered_map headers; void set_json(const std::string& json) { body = json; content_type = "application/json"; } void set_text(const std::string& text) { body = text; content_type = "text/plain"; } void set_html(const std::string& html) { body = html; content_type = "text/html"; } }; class HttpResponseBuilder { private: static constexpr size_t BUFFER_SIZE = 4096; static constexpr const char* STATUS_LINES[] = { "HTTP/1.1 200 OK\r\n", "HTTP/1.1 201 Created\r\n", "HTTP/1.1 400 Bad Request\r\n", "HTTP/1.1 404 Not Found\r\n", "HTTP/1.1 500 Internal Server Error\r\n" }; static int get_status_index(int status) { switch (status) { case 200: return 0; case 201: return 1; case 400: return 2; case 404: return 3; case 500: return 4; default: return -1; } } public: static std::string build_response(const HttpResponse& response, string_view version = "HTTP/1.1") { std::string result; result.reserve(BUFFER_SIZE); // Status line int status_idx = get_status_index(response.status); if (status_idx >= 0) { result += STATUS_LINES[status_idx]; } else { result += version; result += " "; result += std::to_string(response.status); result += " Unknown\r\n"; } // Content headers result += "Content-Type: "; result += response.content_type; result += "\r\nContent-Length: "; result += std::to_string(response.body.size()); result += "\r\n"; // Custom headers for (const auto& [key, value] : response.headers) { result += key; result += ": "; result += value; result += "\r\n"; } // Connection handling bool keep_alive = version != "HTTP/1.0"; if (response.headers.find("Connection") == response.headers.end()) { result += keep_alive ? "Connection: keep-alive\r\n" : "Connection: close\r\n"; } result += "\r\n"; result += response.body; return result; } // Fast path for common responses static std::string build_error_response(int status, string_view message, string_view version = "HTTP/1.1") { std::string result; result.reserve(256); int status_idx = get_status_index(status); if (status_idx >= 0) { result += STATUS_LINES[status_idx]; } else { result += version; result += " "; result += std::to_string(status); result += " Error\r\n"; } result += "Content-Type: text/plain\r\nContent-Length: "; result += std::to_string(message.size()); result += "\r\nConnection: close\r\n\r\n"; result += message; return result; } };