diff --git a/examples/WebSocketClientSockJsAndStomp/WebSocketClientSockJsAndStomp.ino b/examples/WebSocketClientSockJsAndStomp/WebSocketClientSockJsAndStomp.ino new file mode 100644 index 0000000..078b547 --- /dev/null +++ b/examples/WebSocketClientSockJsAndStomp/WebSocketClientSockJsAndStomp.ino @@ -0,0 +1,147 @@ +/* + WebSocketClientSockJsAndStomp.ino + + Example for connecting and maintining a connection with a SockJS+STOMP websocket connection. + In this example we connect to a Spring application (see https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html). + + Created on: 18.07.2017 + Author: Martin Becker , Contact: becker@informatik.uni-wuerzburg.de +*/ + +// PRE + +#define USE_SERIAL Serial + + +// LIBRARIES + +#include +#include + + +// SETTINGS + +const char* wlan_ssid = "yourssid"; +const char* wlan_password = "somepassword"; + +const char* ws_host = "the.host.net"; +const int ws_port = 80; + +// base URL for SockJS (websocket) connection +// The complete URL will look something like this(cf. http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-36): +// ws://://<3digits>//websocket +// For the default config of Spring's SockJS/STOMP support the default base URL is "/socketentry/". +const char* ws_baseurl = "/socketentry/"; // don't forget leading and trailing "/" !!! + + +// VARIABLES + +WebSocketsClient webSocket; + + +// FUNCTIONS + +void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { + + switch (type) { + case WStype_DISCONNECTED: + USE_SERIAL.printf("[WSc] Disconnected!\n"); + break; + case WStype_CONNECTED: + { + USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); + } + break; + case WStype_TEXT: + { + // ##################### + // handle STOMP protocol + // ##################### + + String text = (char*) payload; + + USE_SERIAL.printf("[WSc] get text: %s\n", payload); + + if (payload[0] == 'h') { + + USE_SERIAL.println("Heartbeat!"); + + } else if (payload[0] == 'o') { + + // on open connection + char *msg = "[\"CONNECT\\naccept-version:1.1,1.0\\nheart-beat:10000,10000\\n\\n\\u0000\"]"; + webSocket.sendTXT(msg); + + } else if (text.startsWith("a[\"CONNECTED")) { + + // subscribe to some channels + + char *msg = "[\"SUBSCRIBE\\nid:sub-0\\ndestination:/user/queue/messages\\n\\n\\u0000\"]"; + webSocket.sendTXT(msg); + delay(1000); + + // and send a message + + msg = "[\"SEND\\ndestination:/app/message\\n\\n{\\\"user\\\":\\\"esp\\\",\\\"message\\\":\\\"Hello!\\\"}\\u0000\"]"; + webSocket.sendTXT(msg); + delay(1000); + } + + break; + } + case WStype_BIN: + USE_SERIAL.printf("[WSc] get binary length: %u\n", length); + hexdump(payload, length); + + // send data to server + // webSocket.sendBIN(payload, length); + break; + } + +} + +void setup() { + + // setup serial + + // USE_SERIAL.begin(921600); + USE_SERIAL.begin(115200); + + // USE_SERIAL.setDebugOutput(true); + + USE_SERIAL.println(); + + + // connect to WiFi + + USE_SERIAL.print("Logging into WLAN: "); Serial.print(wlan_ssid); Serial.print(" ..."); + WiFi.mode(WIFI_STA); + WiFi.begin(wlan_ssid, wlan_password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + USE_SERIAL.print("."); + } + USE_SERIAL.println(" success."); + USE_SERIAL.print("IP: "); USE_SERIAL.println(WiFi.localIP()); + + + // ##################### + // create socket url according to SockJS protocol (cf. http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-36) + // ##################### + String socketUrl = ws_baseurl; + socketUrl += random(0, 999); + socketUrl += "/"; + socketUrl += random(0, 999999); // should be a random string, but this works (see ) + socketUrl += "/websocket"; + + // connect to websocket + webSocket.begin(ws_host, ws_port, socketUrl); + webSocket.setExtraHeaders(); // remove "Origin: file://" header because it breaks the connection with Spring's default websocket config + // webSocket.setExtraHeaders("foo: I am so funny\r\nbar: not"); // some headers, in case you feel funny + webSocket.onEvent(webSocketEvent); +} + +void loop() { + webSocket.loop(); +} diff --git a/src/WebSockets.h b/src/WebSockets.h index 1e62469..41cbe7d 100644 --- a/src/WebSockets.h +++ b/src/WebSockets.h @@ -226,6 +226,8 @@ typedef struct { String base64Authorization; ///< Base64 encoded Auth request String plainAuthorization; ///< Base64 encoded Auth request + String extraHeaders; + bool cHttpHeadersValid; ///< non-websocket http header validity indicator size_t cMandatoryHeadersCount; ///< non-websocket mandatory http headers present count diff --git a/src/WebSocketsClient.cpp b/src/WebSocketsClient.cpp index 819af0e..3faae99 100644 --- a/src/WebSocketsClient.cpp +++ b/src/WebSocketsClient.cpp @@ -29,6 +29,7 @@ WebSocketsClient::WebSocketsClient() { _cbEvent = NULL; _client.num = 0; + _client.extraHeaders = WEBSOCKETS_STRING("Origin: file://"); } WebSocketsClient::~WebSocketsClient() { @@ -274,6 +275,15 @@ void WebSocketsClient::setAuthorization(const char * auth) { } } +/** + * set extra headers for the http request; + * separate headers by "\r\n" + * @param extraHeaders const char * extraHeaders + */ +void WebSocketsClient::setExtraHeaders(const char * extraHeaders) { + _client.extraHeaders = extraHeaders; +} + //################################################################################# //################################################################################# //################################################################################# @@ -479,8 +489,12 @@ void WebSocketsClient::sendHeader(WSclient_t * client) { handshake += WEBSOCKETS_STRING("Connection: keep-alive\r\n"); } - handshake += WEBSOCKETS_STRING("Origin: file://\r\n" - "User-Agent: arduino-WebSocket-Client\r\n"); + // add extra headers; by default this includes "Origin: file://" + if (client->extraHeaders) { + handshake += client->extraHeaders + NEW_LINE; + } + + handshake += WEBSOCKETS_STRING("User-Agent: arduino-WebSocket-Client\r\n"); if(client->base64Authorization.length() > 0) { handshake += WEBSOCKETS_STRING("Authorization: Basic "); diff --git a/src/WebSocketsClient.h b/src/WebSocketsClient.h index d8b6814..7390a76 100644 --- a/src/WebSocketsClient.h +++ b/src/WebSocketsClient.h @@ -80,6 +80,8 @@ class WebSocketsClient: private WebSockets { void setAuthorization(const char * user, const char * password); void setAuthorization(const char * auth); + + void setExtraHeaders(const char * extraHeaders = NULL); protected: String _host;