Skip to content

Commit 907257f

Browse files
authored
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
1 parent 0c2f535 commit 907257f

2 files changed

Lines changed: 66 additions & 1 deletion

File tree

httplib.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3848,6 +3848,7 @@ class WebSocketClient {
38483848
void set_socket_options(SocketOptions socket_options);
38493849
void set_connection_timeout(time_t sec, time_t usec = 0);
38503850
void set_interface(const std::string &intf);
3851+
void set_hostname_addr_map(std::map<std::string, std::string> addr_map);
38513852

38523853
#ifdef CPPHTTPLIB_SSL_ENABLED
38533854
void set_ca_cert_path(const std::string &path);
@@ -3882,6 +3883,9 @@ class WebSocketClient {
38823883
time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
38833884
std::string interface_;
38843885

3886+
// Hostname-IP map
3887+
std::map<std::string, std::string> addr_map_;
3888+
38853889
#ifdef CPPHTTPLIB_SSL_ENABLED
38863890
bool is_ssl_ = false;
38873891
tls::ctx_t tls_ctx_ = nullptr;
@@ -20326,9 +20330,14 @@ inline bool WebSocketClient::connect() {
2032620330
if (!is_valid_) { return false; }
2032720331
shutdown_and_close();
2032820332

20333+
// Check is custom IP specified for host_
20334+
std::string ip;
20335+
auto it = addr_map_.find(host_);
20336+
if (it != addr_map_.end()) { ip = it->second; }
20337+
2032920338
Error error;
2033020339
sock_ = detail::create_client_socket(
20331-
host_, std::string(), port_, address_family_, tcp_nodelay_, ipv6_v6only_,
20340+
host_, ip, port_, address_family_, tcp_nodelay_, ipv6_v6only_,
2033220341
socket_options_, connection_timeout_sec_, connection_timeout_usec_,
2033320342
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
2033420343
write_timeout_usec_, interface_, error);
@@ -20423,6 +20432,11 @@ inline void WebSocketClient::set_interface(const std::string &intf) {
2042320432
interface_ = intf;
2042420433
}
2042520434

20435+
inline void WebSocketClient::set_hostname_addr_map(
20436+
std::map<std::string, std::string> addr_map) {
20437+
addr_map_ = std::move(addr_map);
20438+
}
20439+
2042620440
#ifdef CPPHTTPLIB_SSL_ENABLED
2042720441

2042820442
inline void WebSocketClient::set_ca_cert_path(const std::string &path) {

test/test.cc

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17706,6 +17706,57 @@ TEST(WebSocketTest, ComplexPath) {
1770617706
EXPECT_TRUE(ws2.is_valid());
1770717707
}
1770817708

17709+
TEST(WebSocketTest, SpecifyServerIPAddress_AnotherHostname) {
17710+
Server svr;
17711+
svr.WebSocket("/ws", [](const Request &, ws::WebSocket &ws) {
17712+
std::string msg;
17713+
while (ws.read(msg)) {}
17714+
});
17715+
17716+
auto port = svr.bind_to_any_port(HOST);
17717+
std::thread t([&]() { svr.listen_after_bind(); });
17718+
svr.wait_until_ready();
17719+
17720+
auto another_host = "example.com";
17721+
auto wrong_ip = "192.0.2.1";
17722+
17723+
ws::WebSocketClient client("ws://localhost:" + std::to_string(port) + "/ws");
17724+
client.set_hostname_addr_map({{another_host, wrong_ip}});
17725+
17726+
ASSERT_TRUE(client.connect());
17727+
EXPECT_TRUE(client.is_open());
17728+
client.close();
17729+
17730+
svr.stop();
17731+
t.join();
17732+
}
17733+
17734+
TEST(WebSocketTest, SpecifyServerIPAddress_RealHostname) {
17735+
Server svr;
17736+
svr.WebSocket("/ws", [](const Request &, ws::WebSocket &ws) {
17737+
std::string msg;
17738+
while (ws.read(msg)) {}
17739+
});
17740+
17741+
auto port = svr.bind_to_any_port(HOST);
17742+
std::thread t([&]() { svr.listen_after_bind(); });
17743+
svr.wait_until_ready();
17744+
17745+
auto wrong_ip = "192.0.2.1";
17746+
17747+
ws::WebSocketClient client("ws://localhost:" + std::to_string(port) + "/ws");
17748+
client.set_hostname_addr_map({{"localhost", wrong_ip}});
17749+
client.set_connection_timeout(1);
17750+
client.set_read_timeout(1);
17751+
client.set_write_timeout(1);
17752+
17753+
EXPECT_FALSE(client.connect());
17754+
EXPECT_FALSE(client.is_open());
17755+
17756+
svr.stop();
17757+
t.join();
17758+
}
17759+
1770917760
class WebSocketIntegrationTest : public ::testing::Test {
1771017761
protected:
1771117762
void SetUp() override {

0 commit comments

Comments
 (0)