mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-30 13:00:42 +00:00
Add set_basic_auth and set_bearer_token_auth to WebSocketClient (#2652)
ClientImpl and SSLClient let callers set origin credentials with set_basic_auth()/set_bearer_token_auth(), but WebSocketClient could only take a fixed Authorization header through its constructor. Add both setters: each connect() adds the Authorization header to the upgrade request from the current credentials (Basic over Bearer), unless the constructor headers already carry one, and never to the proxy's CONNECT request.
This commit is contained in:
1 parent
290c4c0bbe
commit
a0ab09fc0a
3 files changed
+157
No files matched your search
+117
@@ -32199,8 +32199,106 @@ void WebSocketCredentialsStayWithTheirHop(
|
||||
<< "origin credentials must not be sent to the proxy";
|
||||
}
|
||||
|
||||
// Like WebSocketCredentialsStayWithTheirHop(), but with the setters.
|
||||
void WebSocketSetterCredentialsStayWithTheirHop(
|
||||
const std::function<void(ws::WebSocketClient &)> &set_credentials,
|
||||
const std::string &proxy_authz, const std::string &origin_authz) {
|
||||
ScopedWebSocketOrigin origin;
|
||||
ScopedConnectProxy proxy(
|
||||
origin.port(), require_proxy_auth(proxy_authz, "Basic realm=\"proxy\""));
|
||||
ASSERT_NE(0, proxy.port());
|
||||
|
||||
ws::WebSocketClient client(origin.url());
|
||||
client.set_proxy("127.0.0.1", proxy.port());
|
||||
set_credentials(client);
|
||||
auto res = client.connect();
|
||||
ASSERT_TRUE(res) << "Error: " << to_string(res.error());
|
||||
|
||||
std::string msg;
|
||||
ASSERT_TRUE(client.read(msg));
|
||||
EXPECT_EQ("authorization:" + origin_authz + "|proxy-authorization:", msg);
|
||||
client.close();
|
||||
|
||||
EXPECT_EQ(1, proxy.connect_hits());
|
||||
EXPECT_EQ(std::string::npos,
|
||||
proxy.connect_request().find("\r\nAuthorization: "))
|
||||
<< "origin credentials must not be sent to the proxy";
|
||||
}
|
||||
|
||||
} // namespace proxy_tunnel_test
|
||||
|
||||
namespace {
|
||||
|
||||
// Connects `client` and returns the Authorization header its upgrade
|
||||
// request carried, or "<failed>" when the connection could not be opened.
|
||||
std::string websocket_authorization(ws::WebSocketClient &client) {
|
||||
if (!client.connect()) { return "<failed>"; }
|
||||
std::string msg;
|
||||
if (!client.read(msg)) { return "<failed>"; }
|
||||
client.close();
|
||||
auto prefix = std::string("authorization:");
|
||||
auto end = msg.find("|proxy-authorization:");
|
||||
return msg.substr(prefix.size(), end - prefix.size());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(WebSocketClientAuthTest, BasicAuth) {
|
||||
proxy_tunnel_test::ScopedWebSocketOrigin origin;
|
||||
ws::WebSocketClient client(origin.url());
|
||||
client.set_basic_auth("user", "pass");
|
||||
EXPECT_EQ("Basic " + detail::base64_encode("user:pass"),
|
||||
websocket_authorization(client));
|
||||
}
|
||||
|
||||
TEST(WebSocketClientAuthTest, BasicAuthWithEmptyPasswordIsSent) {
|
||||
proxy_tunnel_test::ScopedWebSocketOrigin origin;
|
||||
ws::WebSocketClient client(origin.url());
|
||||
client.set_basic_auth("user", "");
|
||||
EXPECT_EQ("Basic " + detail::base64_encode("user:"),
|
||||
websocket_authorization(client));
|
||||
}
|
||||
|
||||
TEST(WebSocketClientAuthTest, BearerTokenAuth) {
|
||||
proxy_tunnel_test::ScopedWebSocketOrigin origin;
|
||||
ws::WebSocketClient client(origin.url());
|
||||
client.set_bearer_token_auth("token123");
|
||||
EXPECT_EQ("Bearer token123", websocket_authorization(client));
|
||||
}
|
||||
|
||||
TEST(WebSocketClientAuthTest, BasicAuthWinsOverBearerToken) {
|
||||
proxy_tunnel_test::ScopedWebSocketOrigin origin;
|
||||
ws::WebSocketClient client(origin.url());
|
||||
client.set_bearer_token_auth("token123");
|
||||
client.set_basic_auth("user", "pass");
|
||||
EXPECT_EQ("Basic " + detail::base64_encode("user:pass"),
|
||||
websocket_authorization(client));
|
||||
}
|
||||
|
||||
TEST(WebSocketClientAuthTest, ConstructorHeaderWinsOverSetter) {
|
||||
proxy_tunnel_test::ScopedWebSocketOrigin origin;
|
||||
ws::WebSocketClient client(origin.url(),
|
||||
{{"Authorization", "Bearer from-header"}});
|
||||
client.set_bearer_token_auth("from-setter");
|
||||
client.set_basic_auth("user", "pass");
|
||||
EXPECT_EQ("Bearer from-header", websocket_authorization(client));
|
||||
}
|
||||
|
||||
TEST(WebSocketClientAuthTest, CredentialsApplyOnReconnect) {
|
||||
proxy_tunnel_test::ScopedWebSocketOrigin origin;
|
||||
ws::WebSocketClient client(origin.url());
|
||||
EXPECT_EQ("", websocket_authorization(client));
|
||||
|
||||
client.set_bearer_token_auth("first");
|
||||
EXPECT_EQ("Bearer first", websocket_authorization(client));
|
||||
|
||||
client.set_bearer_token_auth("second");
|
||||
EXPECT_EQ("Bearer second", websocket_authorization(client));
|
||||
|
||||
client.set_bearer_token_auth("");
|
||||
EXPECT_EQ("", websocket_authorization(client));
|
||||
}
|
||||
|
||||
TEST(WebSocketProxyTest, TunnelsThroughConnect) {
|
||||
proxy_tunnel_test::ScopedWebSocketOrigin origin;
|
||||
proxy_tunnel_test::ScopedConnectProxy proxy(origin.port());
|
||||
@@ -32243,6 +32341,25 @@ TEST(WebSocketProxyTest, BearerCredentialsStayWithTheirHop) {
|
||||
"Bearer proxy-token", "Bearer origin-token");
|
||||
}
|
||||
|
||||
TEST(WebSocketProxyTest, BasicAuthSetterStaysWithItsHop) {
|
||||
proxy_tunnel_test::WebSocketSetterCredentialsStayWithTheirHop(
|
||||
[](ws::WebSocketClient &cli) {
|
||||
cli.set_proxy_basic_auth("proxy-user", "proxy-pass");
|
||||
cli.set_basic_auth("origin-user", "origin-pass");
|
||||
},
|
||||
"Basic " + detail::base64_encode("proxy-user:proxy-pass"),
|
||||
"Basic " + detail::base64_encode("origin-user:origin-pass"));
|
||||
}
|
||||
|
||||
TEST(WebSocketProxyTest, BearerTokenAuthSetterStaysWithItsHop) {
|
||||
proxy_tunnel_test::WebSocketSetterCredentialsStayWithTheirHop(
|
||||
[](ws::WebSocketClient &cli) {
|
||||
cli.set_proxy_bearer_token_auth("proxy-token");
|
||||
cli.set_bearer_token_auth("origin-token");
|
||||
},
|
||||
"Bearer proxy-token", "Bearer origin-token");
|
||||
}
|
||||
|
||||
TEST(WebSocketProxyTest, BasicCredentialsWithEmptyPasswordAreSent) {
|
||||
proxy_tunnel_test::ScopedWebSocketOrigin origin;
|
||||
proxy_tunnel_test::ScopedConnectProxy proxy(
|
||||
|
||||
Reference in new issue
Block a user