ws connect has a new option to send HTTP headers + use WebSocketHttpHeaders instead of unordered_map<string, string>

This commit is contained in:
Benjamin Sergeant 2019-08-26 10:19:09 -07:00
parent 0847e60d2a
commit d3e5a63fa2
12 changed files with 66 additions and 12 deletions

View File

@ -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.

View File

@ -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);
```

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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"))

View File

@ -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);

View File

@ -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);

View File

@ -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;