diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d4f0846..41e5338d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. ## [5.0.7] - 2019-08-23 +- WebSocket: add new option to pass in extra HTTP headers when connecting. +- `ws connect` add new option (-H, works like [curl](https://stackoverflow.com/questions/356705/how-to-send-a-header-using-a-http-request-through-a-curl-call)) to pass in extra HTTP headers when connecting + +If you run against `ws echo_server` you will see the headers being received printed in the terminal. +``` +ws connect -H "foo: bar" -H "baz: buz" ws://127.0.0.1:8008 +``` + - CobraConnection: sets a unique id field for all messages sent to [cobra](https://github.com/machinezone/cobra). - CobraConnection: sets a counter as a field for each event published. diff --git a/README.md b/README.md index bb561e70..c062b5ce 100644 --- a/README.md +++ b/README.md @@ -510,3 +510,13 @@ idle connection. ``` webSocket.setHeartBeatPeriod(45); ``` + +### Supply extra HTTP headers. + +You can set extra HTTP headers to be sent during the WebSocket handshake. + +``` +WebSocketHttpHeaders headers; +headers["foo"] = "bar"; +webSocket.setExtraHeaders(headers); +``` diff --git a/ixwebsocket/IXWebSocket.cpp b/ixwebsocket/IXWebSocket.cpp index 610452ce..d176c2a6 100644 --- a/ixwebsocket/IXWebSocket.cpp +++ b/ixwebsocket/IXWebSocket.cpp @@ -70,7 +70,7 @@ namespace ix std::lock_guard lock(_configMutex); _url = url; } - void WebSocket::setExtraHeaders(const std::unordered_map& headers) + void WebSocket::setExtraHeaders(const WebSocketHttpHeaders& headers) { std::lock_guard lock(_configMutex); _extraHeaders = headers; diff --git a/ixwebsocket/IXWebSocket.h b/ixwebsocket/IXWebSocket.h index 0d9acb77..c7ffb2d7 100644 --- a/ixwebsocket/IXWebSocket.h +++ b/ixwebsocket/IXWebSocket.h @@ -21,7 +21,6 @@ #include #include #include -#include namespace ix { @@ -45,8 +44,9 @@ namespace ix ~WebSocket(); void setUrl(const std::string& url); - void setExtraHeaders(const std::unordered_map& - headers); // send extra headers in client handshake request + + // send extra headers in client handshake request + void setExtraHeaders(const WebSocketHttpHeaders& headers); void setPerMessageDeflateOptions( const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); void setHeartBeatPeriod(int heartBeatPeriodSecs); @@ -114,7 +114,7 @@ namespace ix WebSocketTransport _ws; std::string _url; - std::unordered_map _extraHeaders; + WebSocketHttpHeaders _extraHeaders; WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; mutable std::mutex _configMutex; // protect all config variables access diff --git a/ixwebsocket/IXWebSocketHandshake.cpp b/ixwebsocket/IXWebSocketHandshake.cpp index e9e8c4a2..434f5dab 100644 --- a/ixwebsocket/IXWebSocketHandshake.cpp +++ b/ixwebsocket/IXWebSocketHandshake.cpp @@ -88,7 +88,7 @@ namespace ix } WebSocketInitResult WebSocketHandshake::clientHandshake(const std::string& url, - const std::unordered_map& extraHeaders, + const WebSocketHttpHeaders& extraHeaders, const std::string& host, const std::string& path, int port, diff --git a/ixwebsocket/IXWebSocketHandshake.h b/ixwebsocket/IXWebSocketHandshake.h index adc503df..f3cd8a5b 100644 --- a/ixwebsocket/IXWebSocketHandshake.h +++ b/ixwebsocket/IXWebSocketHandshake.h @@ -53,7 +53,7 @@ namespace ix WebSocketInitResult clientHandshake( const std::string& url, - const std::unordered_map& extraHeaders, + const WebSocketHttpHeaders& extraHeaders, const std::string& host, const std::string& path, int port, diff --git a/ixwebsocket/IXWebSocketTransport.cpp b/ixwebsocket/IXWebSocketTransport.cpp index ada516fd..a1db52b0 100644 --- a/ixwebsocket/IXWebSocketTransport.cpp +++ b/ixwebsocket/IXWebSocketTransport.cpp @@ -129,7 +129,7 @@ namespace ix // Client WebSocketInitResult WebSocketTransport::connectToUrl( const std::string& url, - const std::unordered_map& headers, + const WebSocketHttpHeaders& headers, int timeoutSecs) { std::lock_guard lock(_socketMutex); diff --git a/ixwebsocket/IXWebSocketTransport.h b/ixwebsocket/IXWebSocketTransport.h index 728d6c56..c13a81c5 100644 --- a/ixwebsocket/IXWebSocketTransport.h +++ b/ixwebsocket/IXWebSocketTransport.h @@ -24,7 +24,7 @@ #include #include #include -#include + #include namespace ix @@ -78,7 +78,7 @@ namespace ix WebSocketInitResult connectToUrl( // Client const std::string& url, - const std::unordered_map& headers, + const WebSocketHttpHeaders& headers, int timeoutSecs); WebSocketInitResult connectToSocket(int fd, // Server int timeoutSecs); diff --git a/ws/ws.cpp b/ws/ws.cpp index 4e34e642..e2958a74 100644 --- a/ws/ws.cpp +++ b/ws/ws.cpp @@ -109,6 +109,7 @@ int main(int argc, char** argv) CLI::App* connectApp = app.add_subcommand("connect", "Connect to a remote server"); connectApp->add_option("url", url, "Connection url")->required(); + connectApp->add_option("-H", headers, "Header")->join(); connectApp->add_flag("-d", disableAutomaticReconnection, "Disable Automatic Reconnection"); connectApp->add_flag("-x", disablePerMessageDeflate, "Disable per message deflate"); connectApp->add_flag("-b", binaryMode, "Send in binary mode"); @@ -252,7 +253,7 @@ int main(int argc, char** argv) } else if (app.got_subcommand("connect")) { - ret = ix::ws_connect_main(url, disableAutomaticReconnection, + ret = ix::ws_connect_main(url, headers, disableAutomaticReconnection, disablePerMessageDeflate, binaryMode); } else if (app.got_subcommand("chat")) diff --git a/ws/ws.h b/ws/ws.h index 3f8776f0..d9539f93 100644 --- a/ws/ws.h +++ b/ws/ws.h @@ -31,6 +31,7 @@ namespace ix int ws_chat_main(const std::string& url, const std::string& user); int ws_connect_main(const std::string& url, + const std::string& headers, bool disableAutomaticReconnection, bool disablePerMessageDeflate, bool binaryMode); diff --git a/ws/ws_connect.cpp b/ws/ws_connect.cpp index 71c3cac9..160f7574 100644 --- a/ws/ws_connect.cpp +++ b/ws/ws_connect.cpp @@ -18,6 +18,7 @@ namespace ix { public: WebSocketConnect(const std::string& _url, + const std::string& headers, bool disableAutomaticReconnection, bool disablePerMessageDeflate, bool binaryMode); @@ -30,14 +31,17 @@ namespace ix private: std::string _url; + WebSocketHttpHeaders _headers; ix::WebSocket _webSocket; bool _disablePerMessageDeflate; bool _binaryMode; void log(const std::string& msg); + WebSocketHttpHeaders parseHeaders(const std::string& data); }; WebSocketConnect::WebSocketConnect(const std::string& url, + const std::string& headers, bool disableAutomaticReconnection, bool disablePerMessageDeflate, bool binaryMode) : @@ -49,6 +53,8 @@ namespace ix { _webSocket.disableAutomaticReconnection(); } + + _headers = parseHeaders(headers); } void WebSocketConnect::log(const std::string& msg) @@ -56,6 +62,31 @@ namespace ix std::cout << msg << std::endl; } + WebSocketHttpHeaders WebSocketConnect::parseHeaders(const std::string& data) + { + WebSocketHttpHeaders headers; + + // Split by \n + std::string token; + std::stringstream tokenStream(data); + + while (std::getline(tokenStream, token)) + { + std::size_t pos = token.rfind(':'); + + // Bail out if last '.' is found + if (pos == std::string::npos) continue; + + auto key = token.substr(0, pos); + auto val = token.substr(pos+1); + + std::cerr << key << ": " << val << std::endl; + headers[key] = val; + } + + return headers; + } + void WebSocketConnect::stop() { _webSocket.stop(); @@ -64,6 +95,7 @@ namespace ix void WebSocketConnect::start() { _webSocket.setUrl(_url); + _webSocket.setExtraHeaders(_headers); if (_disablePerMessageDeflate) { @@ -151,12 +183,14 @@ namespace ix } int ws_connect_main(const std::string& url, + const std::string& headers, bool disableAutomaticReconnection, bool disablePerMessageDeflate, bool binaryMode) { std::cout << "Type Ctrl-D to exit prompt..." << std::endl; WebSocketConnect webSocketChat(url, + headers, disableAutomaticReconnection, disablePerMessageDeflate, binaryMode); diff --git a/ws/ws_http_client.cpp b/ws/ws_http_client.cpp index 52b79c17..9effdb33 100644 --- a/ws/ws_http_client.cpp +++ b/ws/ws_http_client.cpp @@ -44,7 +44,7 @@ namespace ix if (pos == std::string::npos) continue; auto key = token.substr(0, pos); - auto val = token.substr(pos+2); + auto val = token.substr(pos+1); std::cerr << key << ": " << val << std::endl; headers[key] = val;