8#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
9#define CPPHTTPLIB_OPENSSL_SUPPORT
27 std::string& http_url) {
29 std::regex ws_regex(R
"(^(wss?)://(.+)$)");
32 if (!std::regex_match(ws_url, matches, ws_regex)) {
33 return absl::InvalidArgumentError(
"Invalid WebSocket URL: " + ws_url);
36 std::string scheme = matches[1].str();
37 std::string rest = matches[2].str();
40 http_url =
"http://" + rest;
41 }
else if (scheme ==
"wss") {
42 http_url =
"https://" + rest;
44 return absl::InvalidArgumentError(
"Invalid WebSocket scheme: " + scheme);
48 return absl::OkStatus();
53 return absl::FailedPreconditionError(
54 "WebSocket already connected or connecting");
63 std::regex url_regex(R
"(^(https?)://([^:/\s]+)(?::(\d+))?(/.*)?)$)");
68 return absl::InvalidArgumentError(
"Invalid HTTP URL: " +
http_endpoint_);
71 std::string scheme = matches[1].str();
72 std::string host = matches[2].str();
73 int port = matches[3].matched ? std::stoi(matches[3].str())
74 : (scheme ==
"https" ? 443 : 80);
77 if (scheme ==
"https") {
78#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
79 client_ = std::make_shared<httplib::Client>(host, port);
80 client_->enable_server_certificate_verification(
false);
83 return absl::UnimplementedError(
84 "WSS not supported: OpenSSL support not compiled in");
87 client_ = std::make_shared<httplib::Client>(host, port);
92 return absl::InternalError(
"Failed to create HTTP client");
96 client_->set_connection_timeout(10);
105 std::chrono::system_clock::now().time_since_epoch().count());
118 return absl::OkStatus();
123 return absl::FailedPreconditionError(
"WebSocket not connected");
127 return absl::InternalError(
"HTTP client not initialized");
133 httplib::Headers headers = {
134 {
"Content-Type",
"text/plain"},
138 auto res =
client_->Post(
"/send", headers, message,
"text/plain");
141 return absl::UnavailableError(
"Failed to send message");
144 if (res->status != 200) {
145 return absl::InternalError(
"Server returned status " +
146 std::to_string(res->status));
149 return absl::OkStatus();
154 return absl::FailedPreconditionError(
"WebSocket not connected");
158 return absl::InternalError(
"HTTP client not initialized");
162 std::string body(
reinterpret_cast<const char*
>(data), length);
164 httplib::Headers headers = {
165 {
"Content-Type",
"application/octet-stream"},
169 auto res =
client_->Post(
"/send-binary", headers, body,
170 "application/octet-stream");
173 return absl::UnavailableError(
"Failed to send binary data");
176 if (res->status != 200) {
177 return absl::InternalError(
"Server returned status " +
178 std::to_string(res->status));
181 return absl::OkStatus();
187 return absl::OkStatus();
197 httplib::Headers headers = {
199 {
"X-Close-Code", std::to_string(code)},
200 {
"X-Close-Reason", reason}
203 client_->Post(
"/close", headers,
"",
"text/plain");
216 return absl::OkStatus();
226 httplib::Headers headers = {
230 auto res =
client_->Get(
"/poll", headers);
244 if (res->status == 200 && !res->body.empty()) {
249 }
else if (res->status == 204) {
252 }
else if (res->status >= 400) {
261 std::this_thread::sleep_for(std::chrono::milliseconds(10));
~HttpLibWebSocket() override
std::atomic< bool > stop_receive_
absl::Status Connect(const std::string &url) override
Connect to a WebSocket server.
std::thread receive_thread_
absl::Status Send(const std::string &message) override
Send a text message.
absl::Status ParseWebSocketUrl(const std::string &ws_url, std::string &http_url)
Parse WebSocket URL into HTTP components.
std::string http_endpoint_
absl::Status SendBinary(const uint8_t *data, size_t length) override
Send a binary message.
void StopReceiveLoop()
Stop the receive loop.
absl::Status Close(int code=1000, const std::string &reason="") override
Close the WebSocket connection.
std::shared_ptr< httplib::Client > client_
void ReceiveLoop()
Background thread for receiving messages (polling)
OpenCallback open_callback_
CloseCallback close_callback_
ErrorCallback error_callback_
MessageCallback message_callback_
#define RETURN_IF_ERROR(expr)