mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-31 13:10:37 +00:00
add set_hostname_addr_map to WebSocketClient (#2463)
* add set_hostname_addr_map to WebSocketClient * add WebSocketTest unit test cases * SpecifyServerIPAddress_AnotherHostname * SpecifyServerIPAddress_RealHostname * Change wrong_ip from 0.0.0.0 to 192.0.2.1 Use 192.0.2.1 (RFC 5737 documentation address) to ensure it acts as a non-routable address and does not alias to loopback. * Fix style check * set short timeout in WebSocketTest.SpecifyServerIPAddress_RealHostname cannot reach wrong_ip
This commit is contained in:
1 parent
0c2f535b74
commit
907257f51d
2 files changed
+66
-1
No files matched your search
@@ -3848,6 +3848,7 @@ public:
|
|||||||
void set_socket_options(SocketOptions socket_options);
|
void set_socket_options(SocketOptions socket_options);
|
||||||
void set_connection_timeout(time_t sec, time_t usec = 0);
|
void set_connection_timeout(time_t sec, time_t usec = 0);
|
||||||
void set_interface(const std::string &intf);
|
void set_interface(const std::string &intf);
|
||||||
|
void set_hostname_addr_map(std::map<std::string, std::string> addr_map);
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_SSL_ENABLED
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
||||||
void set_ca_cert_path(const std::string &path);
|
void set_ca_cert_path(const std::string &path);
|
||||||
@@ -3882,6 +3883,9 @@ private:
|
|||||||
time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
|
time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
|
||||||
std::string interface_;
|
std::string interface_;
|
||||||
|
|
||||||
|
// Hostname-IP map
|
||||||
|
std::map<std::string, std::string> addr_map_;
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_SSL_ENABLED
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
||||||
bool is_ssl_ = false;
|
bool is_ssl_ = false;
|
||||||
tls::ctx_t tls_ctx_ = nullptr;
|
tls::ctx_t tls_ctx_ = nullptr;
|
||||||
@@ -20326,9 +20330,14 @@ inline bool WebSocketClient::connect() {
|
|||||||
if (!is_valid_) { return false; }
|
if (!is_valid_) { return false; }
|
||||||
shutdown_and_close();
|
shutdown_and_close();
|
||||||
|
|
||||||
|
// Check is custom IP specified for host_
|
||||||
|
std::string ip;
|
||||||
|
auto it = addr_map_.find(host_);
|
||||||
|
if (it != addr_map_.end()) { ip = it->second; }
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
sock_ = detail::create_client_socket(
|
sock_ = detail::create_client_socket(
|
||||||
host_, std::string(), port_, address_family_, tcp_nodelay_, ipv6_v6only_,
|
host_, ip, port_, address_family_, tcp_nodelay_, ipv6_v6only_,
|
||||||
socket_options_, connection_timeout_sec_, connection_timeout_usec_,
|
socket_options_, connection_timeout_sec_, connection_timeout_usec_,
|
||||||
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
|
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
|
||||||
write_timeout_usec_, interface_, error);
|
write_timeout_usec_, interface_, error);
|
||||||
@@ -20423,6 +20432,11 @@ inline void WebSocketClient::set_interface(const std::string &intf) {
|
|||||||
interface_ = intf;
|
interface_ = intf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void WebSocketClient::set_hostname_addr_map(
|
||||||
|
std::map<std::string, std::string> addr_map) {
|
||||||
|
addr_map_ = std::move(addr_map);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CPPHTTPLIB_SSL_ENABLED
|
#ifdef CPPHTTPLIB_SSL_ENABLED
|
||||||
|
|
||||||
inline void WebSocketClient::set_ca_cert_path(const std::string &path) {
|
inline void WebSocketClient::set_ca_cert_path(const std::string &path) {
|
||||||
|
|||||||
@@ -17706,6 +17706,57 @@ TEST(WebSocketTest, ComplexPath) {
|
|||||||
EXPECT_TRUE(ws2.is_valid());
|
EXPECT_TRUE(ws2.is_valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(WebSocketTest, SpecifyServerIPAddress_AnotherHostname) {
|
||||||
|
Server svr;
|
||||||
|
svr.WebSocket("/ws", [](const Request &, ws::WebSocket &ws) {
|
||||||
|
std::string msg;
|
||||||
|
while (ws.read(msg)) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
auto port = svr.bind_to_any_port(HOST);
|
||||||
|
std::thread t([&]() { svr.listen_after_bind(); });
|
||||||
|
svr.wait_until_ready();
|
||||||
|
|
||||||
|
auto another_host = "example.com";
|
||||||
|
auto wrong_ip = "192.0.2.1";
|
||||||
|
|
||||||
|
ws::WebSocketClient client("ws://localhost:" + std::to_string(port) + "/ws");
|
||||||
|
client.set_hostname_addr_map({{another_host, wrong_ip}});
|
||||||
|
|
||||||
|
ASSERT_TRUE(client.connect());
|
||||||
|
EXPECT_TRUE(client.is_open());
|
||||||
|
client.close();
|
||||||
|
|
||||||
|
svr.stop();
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(WebSocketTest, SpecifyServerIPAddress_RealHostname) {
|
||||||
|
Server svr;
|
||||||
|
svr.WebSocket("/ws", [](const Request &, ws::WebSocket &ws) {
|
||||||
|
std::string msg;
|
||||||
|
while (ws.read(msg)) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
auto port = svr.bind_to_any_port(HOST);
|
||||||
|
std::thread t([&]() { svr.listen_after_bind(); });
|
||||||
|
svr.wait_until_ready();
|
||||||
|
|
||||||
|
auto wrong_ip = "192.0.2.1";
|
||||||
|
|
||||||
|
ws::WebSocketClient client("ws://localhost:" + std::to_string(port) + "/ws");
|
||||||
|
client.set_hostname_addr_map({{"localhost", wrong_ip}});
|
||||||
|
client.set_connection_timeout(1);
|
||||||
|
client.set_read_timeout(1);
|
||||||
|
client.set_write_timeout(1);
|
||||||
|
|
||||||
|
EXPECT_FALSE(client.connect());
|
||||||
|
EXPECT_FALSE(client.is_open());
|
||||||
|
|
||||||
|
svr.stop();
|
||||||
|
t.join();
|
||||||
|
}
|
||||||
|
|
||||||
class WebSocketIntegrationTest : public ::testing::Test {
|
class WebSocketIntegrationTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
|
|||||||
Reference in new issue
Block a user