From 7b2578644b4a901302b9ab2d8fe21fc2add1e999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Steunou?= Date: Wed, 3 Oct 2018 11:51:40 +0200 Subject: [PATCH] Use 2 fallbacks for ws protocol #74 #75 --- CHANGELOG.md | 7 +++++++ dist/webstomp.js | 15 +++++++++------ dist/webstomp.min.js | 2 +- src/client.js | 10 +++++++--- src/utils.js | 11 +++++++---- 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73511d4..75b94db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.2.5 - 0X Oct. 2018 + +* Use `client.debug` instead of `console.log` for a better control of deprecation warning +* Fallback on 1st STOMP protocol provide at `Client` creation when ws does not provide a protocol (too many edge cases, let responsability of wrong compatibility on user hands) +* 2nd fallback after warning on 1.2 STOMP protocol + + # 1.2.4 - 13 Jul. 2018 * Fix some ts types for default export of webstomp diff --git a/dist/webstomp.js b/dist/webstomp.js index 3eee429..8a43fe1 100644 --- a/dist/webstomp.js +++ b/dist/webstomp.js @@ -95,12 +95,12 @@ 'v12.stomp': VERSIONS.V1_2 }; - function getSupportedVersions(protocol) { + function getSupportedVersion(protocol, debug) { var knownVersion = PROTOCOLS_VERSIONS[protocol]; - if (!knownVersion) { - console.warn('DEPRECATED: ' + protocol + ' is not a recognized STOMP version. In next major client version, this will close the connection.'); + if (!knownVersion && debug) { + debug('DEPRECATED: ' + protocol + ' is not a recognized STOMP version. In next major client version, this will close the connection.'); } - return knownVersion || VERSIONS.supportedVersions(); + return knownVersion || VERSIONS.V1_2; } // Define constants for bytes used throughout the code. @@ -321,7 +321,9 @@ _options$heartbeat = options.heartbeat, heartbeat = _options$heartbeat === undefined ? { outgoing: 10000, incoming: 10000 } : _options$heartbeat, _options$debug = options.debug, - debug = _options$debug === undefined ? true : _options$debug; + debug = _options$debug === undefined ? true : _options$debug, + _options$protocols = options.protocols, + protocols = _options$protocols === undefined ? [] : _options$protocols; this.ws = ws; @@ -341,6 +343,7 @@ // subscription callbacks indexed by subscriber's ID this.subscriptions = {}; this.partialData = ''; + this.protocols = protocols; } // //// Debugging @@ -472,7 +475,7 @@ }; this.ws.onopen = function () { _this.debug('Web Socket Opened...'); - headers['accept-version'] = getSupportedVersions(_this.ws.protocol); + headers['accept-version'] = getSupportedVersion(_this.ws.protocol || _this.protocols[0], _this.debug.bind(_this)); // Check if we already have heart-beat in headers before adding them if (!headers['heart-beat']) { headers['heart-beat'] = [_this.heartbeat.outgoing, _this.heartbeat.incoming].join(','); diff --git a/dist/webstomp.min.js b/dist/webstomp.min.js index 923e977..bcdadc6 100644 --- a/dist/webstomp.min.js +++ b/dist/webstomp.min.js @@ -1 +1 @@ -(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):global.webstomp=factory()})(this,function(){"use strict";var classCallCheck=function(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}};var createClass=function(){function defineProperties(target,props){for(var i=0;i1&&arguments[1]!==undefined?arguments[1]:{};var body=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";classCallCheck(this,Frame);this.command=command;this.headers=headers;this.body=body}createClass(Frame,[{key:"toString",value:function toString(){var _this=this;var lines=[this.command],skipContentLength=this.headers["content-length"]===false;if(skipContentLength)delete this.headers["content-length"];Object.keys(this.headers).forEach(function(name){var value=_this.headers[name];lines.push(name+":"+value)});if(this.body&&!skipContentLength){lines.push("content-length:"+sizeOfUTF8(this.body))}lines.push(BYTES.LF+this.body);return lines.join(BYTES.LF)}}],[{key:"unmarshallSingle",value:function unmarshallSingle(data){var divider=data.search(new RegExp(BYTES.LF+BYTES.LF)),headerLines=data.substring(0,divider).split(BYTES.LF),command=headerLines.shift(),headers={},body="",bodyIndex=divider+2;var _iteratorNormalCompletion=true;var _didIteratorError=false;var _iteratorError=undefined;try{for(var _iterator=headerLines.reverse()[Symbol.iterator](),_step;!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=true){var line=_step.value;var idx=line.indexOf(":");headers[trim(line.substring(0,idx))]=trim(line.substring(idx+1))}}catch(err){_didIteratorError=true;_iteratorError=err}finally{try{if(!_iteratorNormalCompletion&&_iterator.return){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}}if(headers["content-length"]){var len=parseInt(headers["content-length"],10);body=(""+data).substring(bodyIndex,bodyIndex+len)}else{var chr=null;for(var i=bodyIndex;i1&&arguments[1]!==undefined?arguments[1]:{};classCallCheck(this,Client);var _options$binary=options.binary,binary=_options$binary===undefined?false:_options$binary,_options$heartbeat=options.heartbeat,heartbeat=_options$heartbeat===undefined?{outgoing:1e4,incoming:1e4}:_options$heartbeat,_options$debug=options.debug,debug=_options$debug===undefined?true:_options$debug;this.ws=ws;this.ws.binaryType="arraybuffer";this.isBinary=!!binary;this.hasDebug=!!debug;this.connected=false;this.heartbeat=heartbeat||{outgoing:0,incoming:0};this.maxWebSocketFrameSize=16*1024;this.subscriptions={};this.partialData=""}createClass(Client,[{key:"debug",value:function debug(){var _console;if(this.hasDebug)(_console=console).log.apply(_console,arguments)}},{key:"connect",value:function connect(){var _this=this;var _parseConnect2=this._parseConnect.apply(this,arguments),_parseConnect3=slicedToArray(_parseConnect2,3),headers=_parseConnect3[0],connectCallback=_parseConnect3[1],errorCallback=_parseConnect3[2];this.connectCallback=connectCallback;this.debug("Opening Web Socket...");this.ws.onmessage=function(evt){var data=evt.data;if(evt.data instanceof ArrayBuffer){data=typedArrayToUnicodeString(new Uint8Array(evt.data))}_this.serverActivity=Date.now();if(data===BYTES.LF){_this.debug("<<< PONG");return}_this.debug("<<< "+data);var unmarshalledData=Frame.unmarshall(_this.partialData+data);_this.partialData=unmarshalledData.partial;unmarshalledData.frames.forEach(function(frame){switch(frame.command){case"CONNECTED":_this.debug("connected to server "+frame.headers.server);_this.connected=true;_this.version=frame.headers.version;_this._setupHeartbeat(frame.headers);if(connectCallback)connectCallback(frame);break;case"MESSAGE":var subscription=frame.headers.subscription;var onreceive=_this.subscriptions[subscription]||_this.onreceive;if(onreceive){var messageID=_this.version===VERSIONS.V1_2&&frame.headers.ack||frame.headers["message-id"];frame.ack=_this.ack.bind(_this,messageID,subscription);frame.nack=_this.nack.bind(_this,messageID,subscription);onreceive(frame)}else{_this.debug("Unhandled received MESSAGE: "+frame)}break;case"RECEIPT":if(_this.onreceipt)_this.onreceipt(frame);break;case"ERROR":if(errorCallback)errorCallback(frame);break;default:_this.debug("Unhandled frame: "+frame)}})};this.ws.onclose=function(event){_this.debug("Whoops! Lost connection to "+_this.ws.url+":",{event:event});_this._cleanUp();if(errorCallback)errorCallback(event)};this.ws.onopen=function(){_this.debug("Web Socket Opened...");headers["accept-version"]=getSupportedVersions(_this.ws.protocol);if(!headers["heart-beat"]){headers["heart-beat"]=[_this.heartbeat.outgoing,_this.heartbeat.incoming].join(",")}_this._transmit("CONNECT",headers)};if(this.ws.readyState===this.ws.OPEN){this.ws.onopen()}}},{key:"disconnect",value:function disconnect(disconnectCallback){var headers=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};this._transmit("DISCONNECT",headers);this.ws.onclose=null;this.ws.close();this._cleanUp();if(disconnectCallback)disconnectCallback()}},{key:"send",value:function send(destination){var body=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var headers=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var hdrs=Object.assign({},headers);hdrs.destination=destination;this._transmit("SEND",hdrs,body)}},{key:"begin",value:function begin(){var transaction=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"tx-"+createId();this._transmit("BEGIN",{transaction:transaction});return{id:transaction,commit:this.commit.bind(this,transaction),abort:this.abort.bind(this,transaction)}}},{key:"commit",value:function commit(transaction){this._transmit("COMMIT",{transaction:transaction})}},{key:"abort",value:function abort(transaction){this._transmit("ABORT",{transaction:transaction})}},{key:"ack",value:function ack(messageID,subscription){var headers=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var hdrs=Object.assign({},headers);var idAttr=this.version===VERSIONS.V1_2?"id":"message-id";hdrs[idAttr]=messageID;hdrs.subscription=subscription;this._transmit("ACK",hdrs)}},{key:"nack",value:function nack(messageID,subscription){var headers=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var hdrs=Object.assign({},headers);var idAttr=this.version===VERSIONS.V1_2?"id":"message-id";hdrs[idAttr]=messageID;hdrs.subscription=subscription;this._transmit("NACK",hdrs)}},{key:"subscribe",value:function subscribe(destination,callback){var headers=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var hdrs=Object.assign({},headers);if(!hdrs.id)hdrs.id="sub-"+createId();hdrs.destination=destination;this.subscriptions[hdrs.id]=callback;this._transmit("SUBSCRIBE",hdrs);return{id:hdrs.id,unsubscribe:this.unsubscribe.bind(this,hdrs.id)}}},{key:"unsubscribe",value:function unsubscribe(id){var headers=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var hdrs=Object.assign({},headers);delete this.subscriptions[id];hdrs.id=id;this._transmit("UNSUBSCRIBE",hdrs)}},{key:"_cleanUp",value:function _cleanUp(){this.connected=false;clearInterval(this.pinger);clearInterval(this.ponger)}},{key:"_transmit",value:function _transmit(command,headers,body){var out=Frame.marshall(command,headers,body);this.debug(">>> "+out,{frame:{command:command,headers:headers,body:body}});this._wsSend(out)}},{key:"_wsSend",value:function _wsSend(data){if(this.isBinary)data=unicodeStringToTypedArray(data);this.debug(">>> length "+data.length);while(true){if(data.length>this.maxWebSocketFrameSize){this.ws.send(data.slice(0,this.maxWebSocketFrameSize));data=data.slice(this.maxWebSocketFrameSize);this.debug("remaining = "+data.length)}else{return this.ws.send(data)}}}},{key:"_setupHeartbeat",value:function _setupHeartbeat(headers){var _this2=this;if(this.version!==VERSIONS.V1_1&&this.version!==VERSIONS.V1_2)return;var _split$map=(headers["heart-beat"]||"0,0").split(",").map(function(v){return parseInt(v,10)}),_split$map2=slicedToArray(_split$map,2),serverOutgoing=_split$map2[0],serverIncoming=_split$map2[1];if(!(this.heartbeat.outgoing===0||serverIncoming===0)){var ttl=Math.max(this.heartbeat.outgoing,serverIncoming);this.debug("send PING every "+ttl+"ms");this.pinger=setInterval(function(){_this2._wsSend(BYTES.LF);_this2.debug(">>> PING")},ttl)}if(!(this.heartbeat.incoming===0||serverOutgoing===0)){var _ttl=Math.max(this.heartbeat.incoming,serverOutgoing);this.debug("check PONG every "+_ttl+"ms");this.ponger=setInterval(function(){var delta=Date.now()-_this2.serverActivity;if(delta>_ttl*2){_this2.debug("did not receive server activity for the last "+delta+"ms");_this2.ws.close()}},_ttl)}}},{key:"_parseConnect",value:function _parseConnect(){var headers={},connectCallback=void 0,errorCallback=void 0;for(var _len=arguments.length,args=Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key]}switch(args.length){case 2:headers=args[0];connectCallback=args[1];break;case 3:if(args[1]instanceof Function){headers=args[0];connectCallback=args[1];errorCallback=args[2]}else{headers.login=args[0];headers.passcode=args[1];connectCallback=args[2]}break;case 4:headers.login=args[0];headers.passcode=args[1];connectCallback=args[2];errorCallback=args[3];break;default:headers.login=args[0];headers.passcode=args[1];connectCallback=args[2];errorCallback=args[3];headers.host=args[4]}return[headers,connectCallback,errorCallback]}}]);return Client}();var webstomp={Frame:Frame,VERSIONS:VERSIONS,client:function client(url){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var ws=new WebSocket(url,options.protocols||VERSIONS.supportedProtocols());return new Client(ws,options)},over:function over(){for(var _len=arguments.length,args=Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key]}return new(Function.prototype.bind.apply(Client,[null].concat(args)))}};return webstomp}); \ No newline at end of file +(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):global.webstomp=factory()})(this,function(){"use strict";var classCallCheck=function(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}};var createClass=function(){function defineProperties(target,props){for(var i=0;i1&&arguments[1]!==undefined?arguments[1]:{};var body=arguments.length>2&&arguments[2]!==undefined?arguments[2]:"";classCallCheck(this,Frame);this.command=command;this.headers=headers;this.body=body}createClass(Frame,[{key:"toString",value:function toString(){var _this=this;var lines=[this.command],skipContentLength=this.headers["content-length"]===false;if(skipContentLength)delete this.headers["content-length"];Object.keys(this.headers).forEach(function(name){var value=_this.headers[name];lines.push(name+":"+value)});if(this.body&&!skipContentLength){lines.push("content-length:"+sizeOfUTF8(this.body))}lines.push(BYTES.LF+this.body);return lines.join(BYTES.LF)}}],[{key:"unmarshallSingle",value:function unmarshallSingle(data){var divider=data.search(new RegExp(BYTES.LF+BYTES.LF)),headerLines=data.substring(0,divider).split(BYTES.LF),command=headerLines.shift(),headers={},body="",bodyIndex=divider+2;var _iteratorNormalCompletion=true;var _didIteratorError=false;var _iteratorError=undefined;try{for(var _iterator=headerLines.reverse()[Symbol.iterator](),_step;!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=true){var line=_step.value;var idx=line.indexOf(":");headers[trim(line.substring(0,idx))]=trim(line.substring(idx+1))}}catch(err){_didIteratorError=true;_iteratorError=err}finally{try{if(!_iteratorNormalCompletion&&_iterator.return){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}}if(headers["content-length"]){var len=parseInt(headers["content-length"],10);body=(""+data).substring(bodyIndex,bodyIndex+len)}else{var chr=null;for(var i=bodyIndex;i1&&arguments[1]!==undefined?arguments[1]:{};classCallCheck(this,Client);var _options$binary=options.binary,binary=_options$binary===undefined?false:_options$binary,_options$heartbeat=options.heartbeat,heartbeat=_options$heartbeat===undefined?{outgoing:1e4,incoming:1e4}:_options$heartbeat,_options$debug=options.debug,debug=_options$debug===undefined?true:_options$debug,_options$protocols=options.protocols,protocols=_options$protocols===undefined?[]:_options$protocols;this.ws=ws;this.ws.binaryType="arraybuffer";this.isBinary=!!binary;this.hasDebug=!!debug;this.connected=false;this.heartbeat=heartbeat||{outgoing:0,incoming:0};this.maxWebSocketFrameSize=16*1024;this.subscriptions={};this.partialData="";this.protocols=protocols}createClass(Client,[{key:"debug",value:function debug(){var _console;if(this.hasDebug)(_console=console).log.apply(_console,arguments)}},{key:"connect",value:function connect(){var _this=this;var _parseConnect2=this._parseConnect.apply(this,arguments),_parseConnect3=slicedToArray(_parseConnect2,3),headers=_parseConnect3[0],connectCallback=_parseConnect3[1],errorCallback=_parseConnect3[2];this.connectCallback=connectCallback;this.debug("Opening Web Socket...");this.ws.onmessage=function(evt){var data=evt.data;if(evt.data instanceof ArrayBuffer){data=typedArrayToUnicodeString(new Uint8Array(evt.data))}_this.serverActivity=Date.now();if(data===BYTES.LF){_this.debug("<<< PONG");return}_this.debug("<<< "+data);var unmarshalledData=Frame.unmarshall(_this.partialData+data);_this.partialData=unmarshalledData.partial;unmarshalledData.frames.forEach(function(frame){switch(frame.command){case"CONNECTED":_this.debug("connected to server "+frame.headers.server);_this.connected=true;_this.version=frame.headers.version;_this._setupHeartbeat(frame.headers);if(connectCallback)connectCallback(frame);break;case"MESSAGE":var subscription=frame.headers.subscription;var onreceive=_this.subscriptions[subscription]||_this.onreceive;if(onreceive){var messageID=_this.version===VERSIONS.V1_2&&frame.headers.ack||frame.headers["message-id"];frame.ack=_this.ack.bind(_this,messageID,subscription);frame.nack=_this.nack.bind(_this,messageID,subscription);onreceive(frame)}else{_this.debug("Unhandled received MESSAGE: "+frame)}break;case"RECEIPT":if(_this.onreceipt)_this.onreceipt(frame);break;case"ERROR":if(errorCallback)errorCallback(frame);break;default:_this.debug("Unhandled frame: "+frame)}})};this.ws.onclose=function(event){_this.debug("Whoops! Lost connection to "+_this.ws.url+":",{event:event});_this._cleanUp();if(errorCallback)errorCallback(event)};this.ws.onopen=function(){_this.debug("Web Socket Opened...");headers["accept-version"]=getSupportedVersion(_this.ws.protocol||_this.protocols[0],_this.debug.bind(_this));if(!headers["heart-beat"]){headers["heart-beat"]=[_this.heartbeat.outgoing,_this.heartbeat.incoming].join(",")}_this._transmit("CONNECT",headers)};if(this.ws.readyState===this.ws.OPEN){this.ws.onopen()}}},{key:"disconnect",value:function disconnect(disconnectCallback){var headers=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};this._transmit("DISCONNECT",headers);this.ws.onclose=null;this.ws.close();this._cleanUp();if(disconnectCallback)disconnectCallback()}},{key:"send",value:function send(destination){var body=arguments.length>1&&arguments[1]!==undefined?arguments[1]:"";var headers=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var hdrs=Object.assign({},headers);hdrs.destination=destination;this._transmit("SEND",hdrs,body)}},{key:"begin",value:function begin(){var transaction=arguments.length>0&&arguments[0]!==undefined?arguments[0]:"tx-"+createId();this._transmit("BEGIN",{transaction:transaction});return{id:transaction,commit:this.commit.bind(this,transaction),abort:this.abort.bind(this,transaction)}}},{key:"commit",value:function commit(transaction){this._transmit("COMMIT",{transaction:transaction})}},{key:"abort",value:function abort(transaction){this._transmit("ABORT",{transaction:transaction})}},{key:"ack",value:function ack(messageID,subscription){var headers=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var hdrs=Object.assign({},headers);var idAttr=this.version===VERSIONS.V1_2?"id":"message-id";hdrs[idAttr]=messageID;hdrs.subscription=subscription;this._transmit("ACK",hdrs)}},{key:"nack",value:function nack(messageID,subscription){var headers=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var hdrs=Object.assign({},headers);var idAttr=this.version===VERSIONS.V1_2?"id":"message-id";hdrs[idAttr]=messageID;hdrs.subscription=subscription;this._transmit("NACK",hdrs)}},{key:"subscribe",value:function subscribe(destination,callback){var headers=arguments.length>2&&arguments[2]!==undefined?arguments[2]:{};var hdrs=Object.assign({},headers);if(!hdrs.id)hdrs.id="sub-"+createId();hdrs.destination=destination;this.subscriptions[hdrs.id]=callback;this._transmit("SUBSCRIBE",hdrs);return{id:hdrs.id,unsubscribe:this.unsubscribe.bind(this,hdrs.id)}}},{key:"unsubscribe",value:function unsubscribe(id){var headers=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var hdrs=Object.assign({},headers);delete this.subscriptions[id];hdrs.id=id;this._transmit("UNSUBSCRIBE",hdrs)}},{key:"_cleanUp",value:function _cleanUp(){this.connected=false;clearInterval(this.pinger);clearInterval(this.ponger)}},{key:"_transmit",value:function _transmit(command,headers,body){var out=Frame.marshall(command,headers,body);this.debug(">>> "+out,{frame:{command:command,headers:headers,body:body}});this._wsSend(out)}},{key:"_wsSend",value:function _wsSend(data){if(this.isBinary)data=unicodeStringToTypedArray(data);this.debug(">>> length "+data.length);while(true){if(data.length>this.maxWebSocketFrameSize){this.ws.send(data.slice(0,this.maxWebSocketFrameSize));data=data.slice(this.maxWebSocketFrameSize);this.debug("remaining = "+data.length)}else{return this.ws.send(data)}}}},{key:"_setupHeartbeat",value:function _setupHeartbeat(headers){var _this2=this;if(this.version!==VERSIONS.V1_1&&this.version!==VERSIONS.V1_2)return;var _split$map=(headers["heart-beat"]||"0,0").split(",").map(function(v){return parseInt(v,10)}),_split$map2=slicedToArray(_split$map,2),serverOutgoing=_split$map2[0],serverIncoming=_split$map2[1];if(!(this.heartbeat.outgoing===0||serverIncoming===0)){var ttl=Math.max(this.heartbeat.outgoing,serverIncoming);this.debug("send PING every "+ttl+"ms");this.pinger=setInterval(function(){_this2._wsSend(BYTES.LF);_this2.debug(">>> PING")},ttl)}if(!(this.heartbeat.incoming===0||serverOutgoing===0)){var _ttl=Math.max(this.heartbeat.incoming,serverOutgoing);this.debug("check PONG every "+_ttl+"ms");this.ponger=setInterval(function(){var delta=Date.now()-_this2.serverActivity;if(delta>_ttl*2){_this2.debug("did not receive server activity for the last "+delta+"ms");_this2.ws.close()}},_ttl)}}},{key:"_parseConnect",value:function _parseConnect(){var headers={},connectCallback=void 0,errorCallback=void 0;for(var _len=arguments.length,args=Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key]}switch(args.length){case 2:headers=args[0];connectCallback=args[1];break;case 3:if(args[1]instanceof Function){headers=args[0];connectCallback=args[1];errorCallback=args[2]}else{headers.login=args[0];headers.passcode=args[1];connectCallback=args[2]}break;case 4:headers.login=args[0];headers.passcode=args[1];connectCallback=args[2];errorCallback=args[3];break;default:headers.login=args[0];headers.passcode=args[1];connectCallback=args[2];errorCallback=args[3];headers.host=args[4]}return[headers,connectCallback,errorCallback]}}]);return Client}();var webstomp={Frame:Frame,VERSIONS:VERSIONS,client:function client(url){var options=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};var ws=new WebSocket(url,options.protocols||VERSIONS.supportedProtocols());return new Client(ws,options)},over:function over(){for(var _len=arguments.length,args=Array(_len),_key=0;_key<_len;_key++){args[_key]=arguments[_key]}return new(Function.prototype.bind.apply(Client,[null].concat(args)))}};return webstomp}); \ No newline at end of file diff --git a/src/client.js b/src/client.js index 1483288..500796b 100644 --- a/src/client.js +++ b/src/client.js @@ -1,5 +1,5 @@ import Frame from './frame'; -import {VERSIONS, BYTES, getSupportedVersions, typedArrayToUnicodeString, unicodeStringToTypedArray, createId} from './utils'; +import {VERSIONS, BYTES, getSupportedVersion, typedArrayToUnicodeString, unicodeStringToTypedArray, createId} from './utils'; // STOMP Client Class // @@ -9,7 +9,7 @@ class Client { constructor(ws, options = {}) { // cannot have default options object + destructuring in the same time in method signature - let {binary = false, heartbeat = {outgoing: 10000, incoming: 10000}, debug = true} = options; + let {binary = false, heartbeat = {outgoing: 10000, incoming: 10000}, debug = true, protocols = []} = options; this.ws = ws; this.ws.binaryType = 'arraybuffer'; @@ -28,6 +28,7 @@ class Client { // subscription callbacks indexed by subscriber's ID this.subscriptions = {}; this.partialData = ''; + this.protocols = protocols; } // //// Debugging @@ -145,7 +146,10 @@ class Client { }; this.ws.onopen = () => { this.debug('Web Socket Opened...'); - headers['accept-version'] = getSupportedVersions(this.ws.protocol); + // 1st protocol fallback on user 1st protocols options + // to prevent edge case where server does not comply and respond with a choosen protocol + // or when ws client does not handle protocol property very well + headers['accept-version'] = getSupportedVersion(this.ws.protocol || this.protocols[0], this.debug.bind(this)); // Check if we already have heart-beat in headers before adding them if (!headers['heart-beat']) { headers['heart-beat'] = [this.heartbeat.outgoing, this.heartbeat.incoming].join(','); diff --git a/src/utils.js b/src/utils.js index 48ac4ab..ab8bba0 100644 --- a/src/utils.js +++ b/src/utils.js @@ -13,12 +13,15 @@ export const PROTOCOLS_VERSIONS = { 'v12.stomp': VERSIONS.V1_2 }; -export function getSupportedVersions(protocol) { +export function getSupportedVersion(protocol, debug) { const knownVersion = PROTOCOLS_VERSIONS[protocol]; - if (!knownVersion) { - console.warn(`DEPRECATED: ${protocol} is not a recognized STOMP version. In next major client version, this will close the connection.`); + if (!knownVersion && debug) { + debug(`DEPRECATED: ${protocol} is not a recognized STOMP version. In next major client version, this will close the connection.`); } - return knownVersion || VERSIONS.supportedVersions(); + // 2nd temporary fallback if the protocol + // does not match a supported STOMP version + // This fallback will be removed in next major version + return knownVersion || VERSIONS.V1_2; } // Define constants for bytes used throughout the code.