ws connect has a new option to send HTTP headers + use WebSocketHttpHeaders instead of unordered_map<string, string>
This commit is contained in:
		| @@ -2,6 +2,14 @@ | |||||||
| All notable changes to this project will be documented in this file. | All notable changes to this project will be documented in this file. | ||||||
|  |  | ||||||
| ## [5.0.7] - 2019-08-23 | ## [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 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. | - CobraConnection: sets a counter as a field for each event published. | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.md
									
									
									
									
									
								
							| @@ -510,3 +510,13 @@ idle connection. | |||||||
| ``` | ``` | ||||||
| webSocket.setHeartBeatPeriod(45); | 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); | ||||||
|  | ``` | ||||||
|   | |||||||
| @@ -70,7 +70,7 @@ namespace ix | |||||||
|         std::lock_guard<std::mutex> lock(_configMutex); |         std::lock_guard<std::mutex> lock(_configMutex); | ||||||
|         _url = url; |         _url = url; | ||||||
|     } |     } | ||||||
|     void WebSocket::setExtraHeaders(const std::unordered_map<std::string, std::string>& headers) |     void WebSocket::setExtraHeaders(const WebSocketHttpHeaders& headers) | ||||||
|     { |     { | ||||||
|         std::lock_guard<std::mutex> lock(_configMutex); |         std::lock_guard<std::mutex> lock(_configMutex); | ||||||
|         _extraHeaders = headers; |         _extraHeaders = headers; | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ | |||||||
| #include <mutex> | #include <mutex> | ||||||
| #include <string> | #include <string> | ||||||
| #include <thread> | #include <thread> | ||||||
| #include <unordered_map> |  | ||||||
|  |  | ||||||
| namespace ix | namespace ix | ||||||
| { | { | ||||||
| @@ -45,8 +44,9 @@ namespace ix | |||||||
|         ~WebSocket(); |         ~WebSocket(); | ||||||
|  |  | ||||||
|         void setUrl(const std::string& url); |         void setUrl(const std::string& url); | ||||||
|         void setExtraHeaders(const std::unordered_map<std::string, std::string>& |  | ||||||
|                                  headers); // send extra headers in client handshake request |         // send extra headers in client handshake request | ||||||
|  |         void setExtraHeaders(const WebSocketHttpHeaders& headers); | ||||||
|         void setPerMessageDeflateOptions( |         void setPerMessageDeflateOptions( | ||||||
|             const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); |             const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); | ||||||
|         void setHeartBeatPeriod(int heartBeatPeriodSecs); |         void setHeartBeatPeriod(int heartBeatPeriodSecs); | ||||||
| @@ -114,7 +114,7 @@ namespace ix | |||||||
|         WebSocketTransport _ws; |         WebSocketTransport _ws; | ||||||
|  |  | ||||||
|         std::string _url; |         std::string _url; | ||||||
|         std::unordered_map<std::string, std::string> _extraHeaders; |         WebSocketHttpHeaders _extraHeaders; | ||||||
|  |  | ||||||
|         WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; |         WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; | ||||||
|         mutable std::mutex _configMutex; // protect all config variables access |         mutable std::mutex _configMutex; // protect all config variables access | ||||||
|   | |||||||
| @@ -88,7 +88,7 @@ namespace ix | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     WebSocketInitResult WebSocketHandshake::clientHandshake(const std::string& url, |     WebSocketInitResult WebSocketHandshake::clientHandshake(const std::string& url, | ||||||
|                                                             const std::unordered_map<std::string, std::string>& extraHeaders, |                                                             const WebSocketHttpHeaders& extraHeaders, | ||||||
|                                                             const std::string& host, |                                                             const std::string& host, | ||||||
|                                                             const std::string& path, |                                                             const std::string& path, | ||||||
|                                                             int port, |                                                             int port, | ||||||
|   | |||||||
| @@ -53,7 +53,7 @@ namespace ix | |||||||
|  |  | ||||||
|         WebSocketInitResult clientHandshake( |         WebSocketInitResult clientHandshake( | ||||||
|             const std::string& url, |             const std::string& url, | ||||||
|             const std::unordered_map<std::string, std::string>& extraHeaders, |             const WebSocketHttpHeaders& extraHeaders, | ||||||
|             const std::string& host, |             const std::string& host, | ||||||
|             const std::string& path, |             const std::string& path, | ||||||
|             int port, |             int port, | ||||||
|   | |||||||
| @@ -129,7 +129,7 @@ namespace ix | |||||||
|     // Client |     // Client | ||||||
|     WebSocketInitResult WebSocketTransport::connectToUrl( |     WebSocketInitResult WebSocketTransport::connectToUrl( | ||||||
|         const std::string& url, |         const std::string& url, | ||||||
|         const std::unordered_map<std::string, std::string>& headers, |         const WebSocketHttpHeaders& headers, | ||||||
|         int timeoutSecs) |         int timeoutSecs) | ||||||
|     { |     { | ||||||
|         std::lock_guard<std::mutex> lock(_socketMutex); |         std::lock_guard<std::mutex> lock(_socketMutex); | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ | |||||||
| #include <memory> | #include <memory> | ||||||
| #include <mutex> | #include <mutex> | ||||||
| #include <string> | #include <string> | ||||||
| #include <unordered_map> |  | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| namespace ix | namespace ix | ||||||
| @@ -78,7 +78,7 @@ namespace ix | |||||||
|  |  | ||||||
|         WebSocketInitResult connectToUrl( // Client |         WebSocketInitResult connectToUrl( // Client | ||||||
|             const std::string& url, |             const std::string& url, | ||||||
|             const std::unordered_map<std::string, std::string>& headers, |             const WebSocketHttpHeaders& headers, | ||||||
|             int timeoutSecs); |             int timeoutSecs); | ||||||
|         WebSocketInitResult connectToSocket(int fd, // Server |         WebSocketInitResult connectToSocket(int fd, // Server | ||||||
|                                             int timeoutSecs); |                                             int timeoutSecs); | ||||||
|   | |||||||
| @@ -109,6 +109,7 @@ int main(int argc, char** argv) | |||||||
|  |  | ||||||
|     CLI::App* connectApp = app.add_subcommand("connect", "Connect to a remote server"); |     CLI::App* connectApp = app.add_subcommand("connect", "Connect to a remote server"); | ||||||
|     connectApp->add_option("url", url, "Connection url")->required(); |     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("-d", disableAutomaticReconnection, "Disable Automatic Reconnection"); | ||||||
|     connectApp->add_flag("-x", disablePerMessageDeflate, "Disable per message deflate"); |     connectApp->add_flag("-x", disablePerMessageDeflate, "Disable per message deflate"); | ||||||
|     connectApp->add_flag("-b", binaryMode, "Send in binary mode"); |     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")) |     else if (app.got_subcommand("connect")) | ||||||
|     { |     { | ||||||
|         ret = ix::ws_connect_main(url, disableAutomaticReconnection, |         ret = ix::ws_connect_main(url, headers, disableAutomaticReconnection, | ||||||
|                                   disablePerMessageDeflate, binaryMode); |                                   disablePerMessageDeflate, binaryMode); | ||||||
|     } |     } | ||||||
|     else if (app.got_subcommand("chat")) |     else if (app.got_subcommand("chat")) | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								ws/ws.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								ws/ws.h
									
									
									
									
									
								
							| @@ -31,6 +31,7 @@ namespace ix | |||||||
|     int ws_chat_main(const std::string& url, const std::string& user); |     int ws_chat_main(const std::string& url, const std::string& user); | ||||||
|  |  | ||||||
|     int ws_connect_main(const std::string& url, |     int ws_connect_main(const std::string& url, | ||||||
|  |                         const std::string& headers, | ||||||
|                         bool disableAutomaticReconnection, |                         bool disableAutomaticReconnection, | ||||||
|                         bool disablePerMessageDeflate, |                         bool disablePerMessageDeflate, | ||||||
|                         bool binaryMode); |                         bool binaryMode); | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ namespace ix | |||||||
|     { |     { | ||||||
|         public: |         public: | ||||||
|             WebSocketConnect(const std::string& _url, |             WebSocketConnect(const std::string& _url, | ||||||
|  |                              const std::string& headers, | ||||||
|                              bool disableAutomaticReconnection, |                              bool disableAutomaticReconnection, | ||||||
|                              bool disablePerMessageDeflate, |                              bool disablePerMessageDeflate, | ||||||
|                              bool binaryMode); |                              bool binaryMode); | ||||||
| @@ -30,14 +31,17 @@ namespace ix | |||||||
|  |  | ||||||
|         private: |         private: | ||||||
|             std::string _url; |             std::string _url; | ||||||
|  |             WebSocketHttpHeaders _headers; | ||||||
|             ix::WebSocket _webSocket; |             ix::WebSocket _webSocket; | ||||||
|             bool _disablePerMessageDeflate; |             bool _disablePerMessageDeflate; | ||||||
|             bool _binaryMode; |             bool _binaryMode; | ||||||
|  |  | ||||||
|             void log(const std::string& msg); |             void log(const std::string& msg); | ||||||
|  |             WebSocketHttpHeaders parseHeaders(const std::string& data); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     WebSocketConnect::WebSocketConnect(const std::string& url, |     WebSocketConnect::WebSocketConnect(const std::string& url, | ||||||
|  |                                        const std::string& headers, | ||||||
|                                        bool disableAutomaticReconnection, |                                        bool disableAutomaticReconnection, | ||||||
|                                        bool disablePerMessageDeflate, |                                        bool disablePerMessageDeflate, | ||||||
|                                        bool binaryMode) : |                                        bool binaryMode) : | ||||||
| @@ -49,6 +53,8 @@ namespace ix | |||||||
|         { |         { | ||||||
|             _webSocket.disableAutomaticReconnection(); |             _webSocket.disableAutomaticReconnection(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         _headers = parseHeaders(headers); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void WebSocketConnect::log(const std::string& msg) |     void WebSocketConnect::log(const std::string& msg) | ||||||
| @@ -56,6 +62,31 @@ namespace ix | |||||||
|         std::cout << msg << std::endl; |         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() |     void WebSocketConnect::stop() | ||||||
|     { |     { | ||||||
|         _webSocket.stop(); |         _webSocket.stop(); | ||||||
| @@ -64,6 +95,7 @@ namespace ix | |||||||
|     void WebSocketConnect::start() |     void WebSocketConnect::start() | ||||||
|     { |     { | ||||||
|         _webSocket.setUrl(_url); |         _webSocket.setUrl(_url); | ||||||
|  |         _webSocket.setExtraHeaders(_headers); | ||||||
|  |  | ||||||
|         if (_disablePerMessageDeflate) |         if (_disablePerMessageDeflate) | ||||||
|         { |         { | ||||||
| @@ -151,12 +183,14 @@ namespace ix | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     int ws_connect_main(const std::string& url, |     int ws_connect_main(const std::string& url, | ||||||
|  |                         const std::string& headers, | ||||||
|                         bool disableAutomaticReconnection, |                         bool disableAutomaticReconnection, | ||||||
|                         bool disablePerMessageDeflate, |                         bool disablePerMessageDeflate, | ||||||
|                         bool binaryMode) |                         bool binaryMode) | ||||||
|     { |     { | ||||||
|         std::cout << "Type Ctrl-D to exit prompt..." << std::endl; |         std::cout << "Type Ctrl-D to exit prompt..." << std::endl; | ||||||
|         WebSocketConnect webSocketChat(url, |         WebSocketConnect webSocketChat(url, | ||||||
|  |                                        headers, | ||||||
|                                        disableAutomaticReconnection, |                                        disableAutomaticReconnection, | ||||||
|                                        disablePerMessageDeflate, |                                        disablePerMessageDeflate, | ||||||
|                                        binaryMode); |                                        binaryMode); | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ namespace ix | |||||||
|             if (pos == std::string::npos) continue; |             if (pos == std::string::npos) continue; | ||||||
|  |  | ||||||
|             auto key = token.substr(0, pos); |             auto key = token.substr(0, pos); | ||||||
|             auto val = token.substr(pos+2); |             auto val = token.substr(pos+1); | ||||||
|  |  | ||||||
|             std::cerr << key << ": " << val << std::endl; |             std::cerr << key << ": " << val << std::endl; | ||||||
|             headers[key] = val; |             headers[key] = val; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user