Skip to content

Commit 79d83fe

Browse files
committed
Fix WebSocketClient dropping query string from URL during handshake (#2468)
The constructor stored only uc.path in path_, discarding uc.query, so the WebSocket upgrade handshake sent the Request-URI without the query string. Append the query to path_ so query parameters (e.g. auth tokens) are sent.
1 parent fe56a07 commit 79d83fe

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

httplib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20266,6 +20266,7 @@ inline WebSocketClient::WebSocketClient(
2026620266
if (!uc.port.empty() && !detail::parse_port(uc.port, port_)) { return; }
2026720267

2026820268
path_ = std::move(uc.path);
20269+
if (!uc.query.empty()) { path_ += uc.query; }
2026920270

2027020271
#ifdef CPPHTTPLIB_SSL_ENABLED
2027120272
is_ssl_ = is_ssl;

test/test.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18191,6 +18191,51 @@ TEST(WebSocketPreRoutingTest, RejectWithoutAuth) {
1819118191
t.join();
1819218192
}
1819318193

18194+
TEST(WebSocketTest, QueryStringInHandshake) {
18195+
Server svr;
18196+
18197+
std::mutex mtx;
18198+
std::string received_target;
18199+
std::string received_token;
18200+
18201+
svr.WebSocket("/ws", [&](const Request &req, ws::WebSocket &ws) {
18202+
{
18203+
std::lock_guard<std::mutex> lock(mtx);
18204+
received_target = req.target;
18205+
if (req.has_param("token")) {
18206+
received_token = req.get_param_value("token");
18207+
}
18208+
}
18209+
std::string msg;
18210+
while (ws.read(msg)) {
18211+
ws.send(msg);
18212+
}
18213+
});
18214+
18215+
auto port = svr.bind_to_any_port("localhost");
18216+
std::thread t([&]() { svr.listen_after_bind(); });
18217+
svr.wait_until_ready();
18218+
18219+
ws::WebSocketClient client("ws://localhost:" + std::to_string(port) +
18220+
"/ws?token=ABC&session=123");
18221+
ASSERT_TRUE(client.connect());
18222+
// Round-trip ensures the handler has run and captured the request.
18223+
ASSERT_TRUE(client.send("hello"));
18224+
std::string msg;
18225+
ASSERT_TRUE(client.read(msg));
18226+
EXPECT_EQ("hello", msg);
18227+
client.close();
18228+
18229+
{
18230+
std::lock_guard<std::mutex> lock(mtx);
18231+
EXPECT_EQ("/ws?token=ABC&session=123", received_target);
18232+
EXPECT_EQ("ABC", received_token);
18233+
}
18234+
18235+
svr.stop();
18236+
t.join();
18237+
}
18238+
1819418239
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
1819518240
class WebSocketSSLIntegrationTest : public ::testing::Test {
1819618241
protected:

0 commit comments

Comments
 (0)