#pragma once #include #include #include #include #include #include #include // Boost.Beast for WebSocket client #include #include #include #include #include #include #include namespace pmc::net { namespace beast = boost::beast; namespace asio = boost::asio; namespace websocket = beast::websocket; using tcp = asio::ip::tcp; enum class HttpMethod { GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS }; class HttpClient { public: HttpClient(); ~HttpClient(); HttpClient(const HttpClient&) = delete; HttpClient& operator=(const HttpClient&) = delete; void set_header(const std::string& header); void clear_headers(); const std::map& get_response_headers() const; long get_response_code() const; // ===== HTTP Methods (Synchronous, libcurl-based) ===== void request_stream_sync( HttpMethod method, const std::string& url, const std::string& data, std::function callback); void get_stream_sync(const std::string& url, std::function callback); void post_stream_sync(const std::string& url, const std::string& data, std::function callback); void put_stream_sync(const std::string& url, const std::string& data, std::function callback); void delete_stream_sync(const std::string& url, std::function callback); // ===== WebSocket Methods (Synchronous, Boost.Beast-based) ===== bool ws_connect(const std::string& url, int timeout_ms = 5000); bool ws_connect(const std::string& host, const std::string& port, const std::string& path = "/", bool ssl = false, int timeout_ms = 5000); bool ws_send(const std::string& message); bool ws_send_binary(const void* data, size_t size); std::string ws_recv(int timeout_ms = 0); bool ws_is_connected() const; void ws_close(); std::string ws_get_host() const; std::string ws_get_port() const; std::string ws_get_path() const; private: CURL* curl_ = nullptr; struct curl_slist* headers_ = nullptr; std::map response_headers_; long response_code_ = 0; struct WsState { asio::io_context ioc; std::unique_ptr tcp_stream; std::unique_ptr ssl_ctx; std::unique_ptr> ssl_stream; std::unique_ptr> ws_stream; std::unique_ptr&>> wss_stream; bool ssl_enabled = false; bool connected = false; std::string host; std::string port; std::string path; }; std::unique_ptr ws_state_; void set_http_method(HttpMethod method, const std::string& data); static size_t header_callback(char* buffer, size_t size, size_t nitems, void* userdata); static size_t write_callback(char* ptr, size_t size, size_t nmemb, void* userdata); static void parse_ws_url(const std::string& url_part, std::string& host, std::string& port, std::string& path, const char* default_port); }; // Backward compatibility aliases using WebSocketClientBase = HttpClient; using WebSocketClient = HttpClient; } // namespace pmc::net