diff --git a/modules/javascript/pom.xml b/modules/javascript/pom.xml
index cd47dd5a..2f5d0a20 100644
--- a/modules/javascript/pom.xml
+++ b/modules/javascript/pom.xml
@@ -3,14 +3,14 @@
org.atmosphere
javascript-project
- 2.0.5-SNAPSHOT
+ 2.0.11-SNAPSHOT
../../pom.xml
4.0.0
org.atmosphere.client
javascript
war
- 2.0.5-SNAPSHOT
+ 2.0.11-SNAPSHOT
javascript
diff --git a/modules/javascript/src/main/webapp/javascript/atmosphere.js b/modules/javascript/src/main/webapp/javascript/atmosphere.js
index eb1c51f9..4c29c969 100644
--- a/modules/javascript/src/main/webapp/javascript/atmosphere.js
+++ b/modules/javascript/src/main/webapp/javascript/atmosphere.js
@@ -28,7 +28,7 @@
"use strict";
- var version = "2.0.5-javascript",
+ var version = "2.0.10-javascript",
atmosphere = {},
guid,
requests = [],
@@ -279,6 +279,8 @@
// Wait to be sure we have the full message before closing.
if (_response.partialMessage === "" && (rq.transport === 'streaming') && (ajaxRequest.responseText.length > rq.maxStreamingLength)) {
_response.messages = [];
+ rq.reconnectingOnLength = true;
+ rq.isReopen = true;
_invokeClose(true);
_disconnect();
_clearState();
@@ -305,9 +307,8 @@
var url = _request.url.replace(/([?&])_=[^&]*/, query);
url = url + (url === _request.url ? (/\?/.test(_request.url) ? "&" : "?") + query : "");
-
var rq = {
- connected: false,
+ connected: false
};
var closeR = new atmosphere.AtmosphereRequest(rq);
closeR.attachHeadersAsQueryString = false;
@@ -315,6 +316,7 @@
closeR.url = url;
closeR.contentType = "text/plain";
closeR.transport = 'polling';
+ closeR.async = false;
_pushOnClose("", closeR);
}
}
@@ -325,6 +327,10 @@
* @private
*/
function _close() {
+ if (_request.reconnectId) {
+ clearTimeout(_request.reconnectId);
+ delete _request.reconnectId;
+ }
_request.reconnect = false;
_abordingConnection = true;
_response.request = _request;
@@ -356,7 +362,7 @@
_activeRequest = null;
}
if (_websocket != null) {
- if (_websocket.webSocketOpened) {
+ if (_websocket.canSendMessage) {
_websocket.close();
}
_websocket = null;
@@ -917,7 +923,21 @@
};
script.onerror = function () {
script.clean();
- _onError(0, "maxReconnectOnClose reached");
+ rq.lastIndex = 0;
+
+ if (rq.openId) {
+ clearTimeout(rq.openId);
+ }
+
+ if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {
+ _open('re-connecting', rq.transport, rq);
+ _reconnect(_jqxhr, rq, request.reconnectInterval);
+ rq.openId = setTimeout(function() {
+ _triggerOpen(rq);
+ }, rq.reconnectInterval + 1000);
+ } else {
+ _onError(0, "maxReconnectOnClose reached");
+ }
};
head.insertBefore(script, head.firstChild);
@@ -1019,7 +1039,7 @@
_response.transport = "sse";
- var location = _buildSSEUrl(_request.url);
+ var location = _buildSSEUrl();
if (_request.logLevel === 'debug') {
atmosphere.util.debug("Invoking executeSSE");
@@ -1068,7 +1088,11 @@
} else {
_open('re-opening', "sse", _request);
}
+ } else if (_request.isReopen) {
+ _request.isReopen = false;
+ _open('re-opening', _request.transport, _request);
}
+
sseOpened = true;
if (_request.method === 'POST') {
@@ -1093,10 +1117,10 @@
// https://github.com/remy/polyfills/blob/master/EventSource.js
// Since we polling.
- if (_sse.URL) {
+ /* if (_sse.URL) {
_sse.interval = 100;
- _sse.URL = _buildSSEUrl(_request.url);
- }
+ _sse.URL = _buildSSEUrl();
+ } */
if (!skipCallbackInvocation) {
_invokeCallback();
@@ -1121,7 +1145,7 @@
if (_requestCount++ < _request.maxReconnectOnClose) {
_open('re-connecting', _request.transport, _request);
if (_request.reconnectInterval > 0) {
- _request.id = setTimeout(function () {
+ _request.reconnectId = setTimeout(function () {
_executeSSE(true);
}, _request.reconnectInterval);
} else {
@@ -1197,18 +1221,22 @@
atmosphere.util.debug("Websocket successfully opened");
}
+ var reopening = webSocketOpened;
+
+ if(_websocket != null) {
+ _websocket.canSendMessage = true;
+ }
+
if (!_request.enableProtocol) {
- if (!webSocketOpened) {
- _open('opening', "websocket", _request);
- } else {
+ webSocketOpened = true;
+ if (reopening) {
_open('re-opening', "websocket", _request);
+ } else {
+ _open('opening', "websocket", _request);
}
}
- webSocketOpened = true;
if (_websocket != null) {
- _websocket.webSocketOpened = webSocketOpened;
-
if (_request.method === 'POST') {
_response.state = "messageReceived";
_websocket.send(_request.data);
@@ -1219,6 +1247,12 @@
_websocket.onmessage = function (message) {
_timeout(_request);
+ // We only consider it opened if we get the handshake data
+ // https://github.com/Atmosphere/atmosphere-javascript/issues/74
+ if (_request.enableProtocol) {
+ webSocketOpened = true;
+ }
+
_response.state = 'messageReceived';
_response.status = 200;
@@ -1302,7 +1336,7 @@
if (_requestCount++ < _request.maxReconnectOnClose) {
_open('re-connecting', _request.transport, _request);
if (_request.reconnectInterval > 0) {
- _request.id = setTimeout(function () {
+ _request.reconnectId = setTimeout(function () {
_response.responseBody = "";
_response.messages = [];
_executeWebSocket(true);
@@ -1332,8 +1366,12 @@
}
function _handleProtocol(request, message) {
+
// The first messages is always the uuid.
var b = true;
+
+ if (request.transport === 'polling') return b;
+
if (atmosphere.util.trim(message).length !== 0 && request.enableProtocol && request.firstMessage) {
request.firstMessage = false;
var messages = message.split(request.messageDelimiter);
@@ -1393,7 +1431,7 @@
* @param response
*/
function _trackMessageSize(message, request, response) {
- if (!_handleProtocol(_request, message))
+ if (!_handleProtocol(request, message))
return true;
if (message.length === 0)
return true;
@@ -1462,7 +1500,7 @@
_response.transport = _request.fallbackTransport;
_request.fallbackTransport = 'none';
if (reconnectInterval > 0) {
- _request.id = setTimeout(function () {
+ _request.reconnectId = setTimeout(function () {
_execute();
}, reconnectInterval);
} else {
@@ -1590,6 +1628,13 @@
}
};
+ var disconnected = function () {
+ // Prevent onerror callback to be called
+ _response.errorHandled = true;
+ _clearState();
+ reconnectF();
+ };
+
if (rq.force || (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest))) {
rq.force = false;
@@ -1620,8 +1665,8 @@
if (!_response.status) {
_response.status = 500;
}
- _clearState();
if (!_response.errorHandled) {
+ _clearState();
reconnectF();
}
};
@@ -1637,6 +1682,9 @@
var update = false;
if (rq.transport === 'streaming' && rq.readyState > 2 && ajaxRequest.readyState === 4) {
+ if (rq.reconnectingOnLength) {
+ return;
+ }
_clearState();
reconnectF();
return;
@@ -1652,34 +1700,35 @@
_timeout(_request);
if (rq.transport !== 'polling') {
- if ((!rq.enableProtocol || !request.firstMessage) && ajaxRequest.readyState === 2) {
- _triggerOpen(rq);
- }
-
// MSIE 9 and lower status can be higher than 1000, Chrome can be 0
var status = 200;
- if (ajaxRequest.readyState > 1) {
+ if (ajaxRequest.readyState === 4) {
status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;
}
if (status >= 300 || status === 0) {
- // Prevent onerror callback to be called
- _response.errorHandled = true;
- _clearState();
- reconnectF();
+ disconnected();
return;
}
+
+ // Firefox incorrectly send statechange 0->2 when a reconnect attempt fails. The above checks ensure that onopen is not called for these
+ if ((!rq.enableProtocol || !request.firstMessage) && ajaxRequest.readyState === 2) {
+ _triggerOpen(rq);
+ }
+
} else if (ajaxRequest.readyState === 4) {
update = true;
}
if (update) {
var responseText = ajaxRequest.responseText;
+ _response.errorHandled = false;
+ // IE behave the same way when resuming long-polling or when the server goes down.
if (atmosphere.util.trim(responseText).length === 0 && rq.transport === 'long-polling') {
// For browser that aren't support onabort
if (!ajaxRequest.hasData) {
- reconnectF();
+ disconnected();
} else {
ajaxRequest.hasData = false;
}
@@ -1769,6 +1818,7 @@
_subscribed = true;
} catch (e) {
atmosphere.util.log(rq.logLevel, ["Unable to connect to " + rq.url]);
+ _onError(0, e);
}
} else {
@@ -1843,15 +1893,21 @@
function _reconnect(ajaxRequest, request, reconnectInterval) {
if (request.reconnect || (request.suspend && _subscribed)) {
var status = 0;
- if (ajaxRequest && ajaxRequest.readyState !== 0) {
+ if (ajaxRequest && ajaxRequest.readyState > 1) {
status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;
}
_response.status = status === 0 ? 204 : status;
_response.reason = status === 0 ? "Server resumed the connection or down." : "OK";
clearTimeout(request.id);
+ if (request.reconnectId) {
+ clearTimeout(request.reconnectId);
+ delete request.reconnectId;
+ }
+
if (reconnectInterval > 0) {
- request.id = setTimeout(function () {
+ // For whatever reason, never cancel a reconnect timeout as it is mandatory to reconnect.
+ _request.reconnectId = setTimeout(function () {
_executeRequest(request);
}, reconnectInterval);
} else {
@@ -1916,7 +1972,7 @@
_clearState();
if (_requestCount++ < rq.maxReconnectOnClose) {
if (rq.reconnectInterval > 0) {
- rq.id = setTimeout(function () {
+ rq.reconnectId = setTimeout(function () {
_open('re-connecting', request.transport, request);
_ieXDR(rq);
}, rq.reconnectInterval);
@@ -2103,7 +2159,7 @@
_invokeClose(true);
_open('re-connecting', rq.transport, rq);
if (rq.reconnectInterval > 0) {
- rq.id = setTimeout(function () {
+ rq.reconnectId = setTimeout(function () {
_ieStreaming(rq);
}, rq.reconnectInterval);
} else {
@@ -2119,7 +2175,7 @@
_open('re-connecting', rq.transport, rq);
if (_requestCount++ < rq.maxReconnectOnClose) {
if (rq.reconnectInterval > 0) {
- rq.id = setTimeout(function () {
+ rq.reconnectId = setTimeout(function () {
_ieStreaming(rq);
}, rq.reconnectInterval);
} else {
@@ -2182,6 +2238,7 @@
rq.reconnect = false;
rq.force = true;
rq.suspend = false;
+ rq.timeout = 1000;
_executeRequest(rq);
}
@@ -2302,7 +2359,7 @@
*
*/
function _pushWebSocket(message) {
- var msg = _getStringMessage(message);
+ var msg = atmosphere.util.isBinary(message) ? message : _getStringMessage(message);
var data;
try {
if (_request.dispatchUrl != null) {
@@ -2311,7 +2368,7 @@
data = msg;
}
- if (!_websocket.webSocketOpened) {
+ if (!_websocket.canSendMessage) {
atmosphere.util.error("WebSocket not connected.");
return;
}
@@ -2350,33 +2407,35 @@
}
function _readHeaders(xdr, request) {
- if (!request.readResponsesHeaders && !request.enableProtocol) {
- request.lastTimestamp = atmosphere.util.now();
- request.uuid = guid;
- return;
- }
-
- try {
- var tempDate = xdr.getResponseHeader('X-Cache-Date');
- if (tempDate && tempDate != null && tempDate.length > 0) {
- request.lastTimestamp = tempDate.split(" ").pop();
+ if (!request.readResponsesHeaders) {
+ if (!request.enableProtocol) {
+ request.lastTimestamp = atmosphere.util.now();
+ request.uuid = guid;
}
+ }
+ else {
+ try {
+ var tempDate = xdr.getResponseHeader('X-Cache-Date');
+ if (tempDate && tempDate != null && tempDate.length > 0) {
+ request.lastTimestamp = tempDate.split(" ").pop();
+ }
- var tempUUID = xdr.getResponseHeader('X-Atmosphere-tracking-id');
- if (tempUUID && tempUUID != null) {
- request.uuid = tempUUID.split(" ").pop();
- }
+ var tempUUID = xdr.getResponseHeader('X-Atmosphere-tracking-id');
+ if (tempUUID && tempUUID != null) {
+ request.uuid = tempUUID.split(" ").pop();
+ }
- // HOTFIX for firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=608735
- if (request.headers) {
- atmosphere.util.each(_request.headers, function (name) {
- var v = xdr.getResponseHeader(name);
- if (v) {
- _response.headers[name] = v;
- }
- });
+ // HOTFIX for firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=608735
+ if (request.headers) {
+ atmosphere.util.each(_request.headers, function (name) {
+ var v = xdr.getResponseHeader(name);
+ if (v) {
+ _response.headers[name] = v;
+ }
+ });
+ }
+ } catch (e) {
}
- } catch (e) {
}
}
@@ -2398,6 +2457,7 @@
f.onError(response);
break;
case "opening":
+ delete _request.closed;
if (typeof (f.onOpen) !== 'undefined')
f.onOpen(response);
break;
@@ -2414,6 +2474,7 @@
f.onClientTimeout(_request);
break;
case "re-opening":
+ delete _request.closed;
if (typeof (f.onReopen) !== 'undefined')
f.onReopen(_request, response);
break;
@@ -2649,8 +2710,8 @@
},
isBinary: function (data) {
- var string = Object.prototype.toString.call(data);
- return string === "[object Blob]" || string === "[object ArrayBuffer]";
+ // True if data is an instance of Blob, ArrayBuffer or ArrayBufferView
+ return /^\[object\s(?:Blob|ArrayBuffer|.+Array)\]$/.test(Object.prototype.toString.call(data));
},
isFunction: function (fn) {
@@ -2982,9 +3043,13 @@
});
// Pressing ESC key in Firefox kills the connection
+ // for your information, this is fixed in Firefox 20
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=614304
atmosphere.util.on(window, "keypress", function (event) {
- if (event.which === 27) {
- event.preventDefault();
+ if (event.charCode === 27 || event.keyCode === 27) {
+ if (event.preventDefault) {
+ event.preventDefault();
+ }
}
});
diff --git a/modules/jquery/pom.xml b/modules/jquery/pom.xml
index ed8bd1f1..7e6d6351 100755
--- a/modules/jquery/pom.xml
+++ b/modules/jquery/pom.xml
@@ -3,14 +3,14 @@
org.atmosphere
javascript-project
- 2.0.5-SNAPSHOT
+ 2.0.11-SNAPSHOT
../../pom.xml
4.0.0
org.atmosphere.client
jquery
war
- 2.0.5-SNAPSHOT
+ 2.0.11-SNAPSHOT
jquery
diff --git a/modules/jquery/src/main/webapp/jquery/jquery.atmosphere.js b/modules/jquery/src/main/webapp/jquery/jquery.atmosphere.js
index a1f7a752..77297444 100644
--- a/modules/jquery/src/main/webapp/jquery/jquery.atmosphere.js
+++ b/modules/jquery/src/main/webapp/jquery/jquery.atmosphere.js
@@ -54,7 +54,7 @@ jQuery.atmosphere = function () {
};
return {
- version: "2.0.5-jquery",
+ version: "2.0.10-jquery",
uuid : 0,
requests: [],
callbacks: [],
@@ -787,8 +787,17 @@ jQuery.atmosphere = function () {
dataType: "jsonp",
error: function (jqXHR, textStatus, errorThrown) {
_response.error = true;
- if (jqXHR.status < 300) {
- _reconnect(_jqxhr, rq, 0);
+
+ if (rq.openId) {
+ clearTimeout(rq.openId);
+ }
+
+ if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {
+ _open('re-connecting', rq.transport, rq);
+ _reconnect(_jqxhr, rq, rq.reconnectInterval);
+ rq.openId = setTimeout(function() {
+ _triggerOpen(rq);
+ }, rq.reconnectInterval + 1000);
} else {
_onError(jqXHR.status, errorThrown);
}
@@ -1001,6 +1010,9 @@ jQuery.atmosphere = function () {
} else {
_open('re-opening', "sse", _request);
}
+ } else if (_request.isReopen) {
+ _request.isReopen = false;
+ _open('re-opening', _request.transport, _request);
}
sseOpened = true;
@@ -1045,7 +1057,7 @@ jQuery.atmosphere = function () {
if (_requestCount++ < _request.maxReconnectOnClose) {
_open('re-connecting', _request.transport, _request);
if (_request.reconnectInterval > 0) {
- _request.id = setTimeout(function () {
+ _request.reconnectId = setTimeout(function () {
_executeSSE(true);
}, _request.reconnectInterval);
} else {
@@ -1120,18 +1132,22 @@ jQuery.atmosphere = function () {
jQuery.atmosphere.debug("Websocket successfully opened");
}
+ var reopening = webSocketOpened;
+
+ if(_websocket != null) {
+ _websocket.canSendMessage = true;
+ }
+
if (!_request.enableProtocol) {
- if (!webSocketOpened) {
- _open('opening', "websocket", _request);
- } else {
+ webSocketOpened = true;
+ if (reopening) {
_open('re-opening', "websocket", _request);
+ } else {
+ _open('opening', "websocket", _request);
}
}
- webSocketOpened = true;
if (_websocket != null) {
- _websocket.webSocketOpened = webSocketOpened;
-
if (_request.method === 'POST') {
_response.state = "messageReceived";
_websocket.send(_request.data);
@@ -1142,6 +1158,12 @@ jQuery.atmosphere = function () {
_websocket.onmessage = function (message) {
_timeout(_request);
+ // We only consider it opened if we get the handshake data
+ // https://github.com/Atmosphere/atmosphere-javascript/issues/74
+ if (_request.enableProtocol) {
+ webSocketOpened = true;
+ }
+
_response.state = 'messageReceived';
_response.status = 200;
@@ -1225,7 +1247,7 @@ jQuery.atmosphere = function () {
if (_requestCount++ < _request.maxReconnectOnClose) {
_open('re-connecting', _request.transport, _request);
if (_request.reconnectInterval > 0) {
- _request.id = setTimeout(function () {
+ _request.reconnectId = setTimeout(function () {
_response.responseBody = "";
_response.messages = [];
_executeWebSocket(true);
@@ -1257,6 +1279,9 @@ jQuery.atmosphere = function () {
function _handleProtocol(request, message) {
// The first messages is always the uuid.
var b = true;
+
+ if (request.transport === 'polling') return b;
+
if (jQuery.trim(message).length !== 0 && request.enableProtocol && request.firstMessage) {
request.firstMessage = false;
var messages = message.split(request.messageDelimiter);
@@ -1317,7 +1342,7 @@ jQuery.atmosphere = function () {
* @param response
*/
function _trackMessageSize(message, request, response) {
- if (!_handleProtocol(_request, message))
+ if (!_handleProtocol(request, message))
return true;
if (message.length === 0)
return true;
@@ -1386,7 +1411,7 @@ jQuery.atmosphere = function () {
_response.transport = _request.fallbackTransport;
_request.fallbackTransport = 'none';
if (reconnectInterval > 0) {
- _request.id = setTimeout(function () {
+ _request.reconnectId = setTimeout(function () {
_execute();
}, reconnectInterval);
} else {
@@ -1519,6 +1544,13 @@ jQuery.atmosphere = function () {
}
};
+ var disconnected = function () {
+ // Prevent onerror callback to be called
+ _response.errorHandled = true;
+ _clearState();
+ reconnectF();
+ };
+
if (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest)) {
var ajaxRequest = jQuery.ajaxSettings.xhr();
ajaxRequest.hasData = false;
@@ -1547,8 +1579,8 @@ jQuery.atmosphere = function () {
if (!_response.status) {
_response.status = 500;
}
- _clearState();
if (!_response.errorHandled) {
+ _clearState();
reconnectF();
}
};
@@ -1564,6 +1596,9 @@ jQuery.atmosphere = function () {
var update = false;
if (rq.transport === 'streaming' && rq.readyState > 2 && ajaxRequest.readyState === 4) {
+ if (rq.reconnectingOnLength) {
+ return;
+ }
_clearState();
reconnectF();
return;
@@ -1579,33 +1614,33 @@ jQuery.atmosphere = function () {
_timeout(_request);
if (rq.transport !== 'polling') {
- if ((!rq.enableProtocol || !request.firstMessage) && ajaxRequest.readyState === 2) {
- _triggerOpen(rq);
- }
// MSIE 9 and lower status can be higher than 1000, Chrome can be 0
var status = 200;
- if (ajaxRequest.readyState > 1) {
+ if (ajaxRequest.readyState === 4) {
status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;
}
if (status >= 300 || status === 0) {
- // Prevent onerror callback to be called
- _response.errorHandled = true;
- _clearState();
- reconnectF();
+ disconnected();
return;
}
+
+ // Firefox incorrectly send statechange 0->2 when a reconnect attempt fails. The above checks ensure that onopen is not called for these
+ if ((!rq.enableProtocol || !request.firstMessage) && ajaxRequest.readyState === 2) {
+ _triggerOpen(rq);
+ }
} else if (ajaxRequest.readyState === 4) {
update = true;
}
if (update) {
var responseText = ajaxRequest.responseText;
+ _response.errorHandled = false;
if (jQuery.trim(responseText.length).length === 0 && rq.transport === 'long-polling') {
// For browser that aren't support onabort
if (!ajaxRequest.hasData) {
- reconnectF();
+ disconnected();
} else {
ajaxRequest.hasData = false;
}
@@ -1764,17 +1799,22 @@ jQuery.atmosphere = function () {
function _reconnect(ajaxRequest, request, reconnectInterval) {
if (request.reconnect || (request.suspend && _subscribed)) {
var status = 0;
- if (ajaxRequest.readyState !== 0) {
+ if (ajaxRequest.readyState > 1) {
status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;
}
_response.status = status === 0 ? 204 : status;
_response.reason = status === 0 ? "Server resumed the connection or down." : "OK";
- // Reconnect immedialtely
+ // Reconnect immediately
clearTimeout(request.id);
+ if (request.reconnectId) {
+ clearTimeout(request.reconnectId);
+ delete request.reconnectId;
+ }
+
if (reconnectInterval > 0) {
- request.id = setTimeout(function () {
- _executeRequest(request);
+ setTimeout(function () {
+ _request.reconnectId = _executeRequest(request);
}, reconnectInterval);
} else {
_executeRequest(request);
@@ -1839,7 +1879,7 @@ jQuery.atmosphere = function () {
_clearState();
if (_requestCount++ < rq.maxReconnectOnClose) {
if (rq.reconnectInterval > 0) {
- rq.id = setTimeout(function () {
+ rq.reconnectId = setTimeout(function () {
_open('re-connecting', request.transport, request);
_ieXDR(rq);
}, rq.reconnectInterval);
@@ -2036,7 +2076,7 @@ jQuery.atmosphere = function () {
_invokeClose(true);
_open('re-connecting', rq.transport, rq);
if (rq.reconnectInterval > 0) {
- rq.id = setTimeout(function () {
+ rq.reconnectId = setTimeout(function () {
_ieStreaming(rq);
}, rq.reconnectInterval);
} else {
@@ -2052,7 +2092,7 @@ jQuery.atmosphere = function () {
_open('re-connecting', rq.transport, rq);
if (_requestCount++ < rq.maxReconnectOnClose) {
if (rq.reconnectInterval > 0) {
- rq.id = setTimeout(function () {
+ rq.reconnectId = setTimeout(function () {
_ieStreaming(rq);
}, rq.reconnectInterval);
} else {
@@ -2229,7 +2269,7 @@ jQuery.atmosphere = function () {
*
*/
function _pushWebSocket(message) {
- var msg = _getStringMessage(message);
+ var msg = jQuery.atmosphere.isBinary(message) ? message : _getStringMessage(message);
var data;
try {
if (_request.dispatchUrl != null) {
@@ -2238,7 +2278,7 @@ jQuery.atmosphere = function () {
data = msg;
}
- if (!_websocket.webSocketOpened) {
+ if (!_websocket.canSendMessage) {
jQuery.atmosphere.error("WebSocket not connected.");
return;
}
@@ -2250,7 +2290,7 @@ jQuery.atmosphere = function () {
};
_clearState();
- _reconnectWithFallbackTransport("Websocket failed. Downgrading to Comet and resending " + data);
+ _reconnectWithFallbackTransport("Websocket failed. Downgrading to Comet and resending " + message);
_pushAjaxMessage(message);
}
}
@@ -2277,33 +2317,35 @@ jQuery.atmosphere = function () {
}
function _readHeaders(xdr, request) {
- if (!request.readResponsesHeaders && !request.enableProtocol) {
- request.lastTimestamp = jQuery.now();
- request.uuid = jQuery.atmosphere.guid();
- return;
- }
-
- try {
- var tempDate = xdr.getResponseHeader('X-Cache-Date');
- if (tempDate && tempDate != null && tempDate.length > 0) {
- request.lastTimestamp = tempDate.split(" ").pop();
+ if (!request.readResponsesHeaders) {
+ if (!request.enableProtocol) {
+ request.lastTimestamp = jQuery.now();
+ request.uuid = jQuery.atmosphere.guid();
}
+ }
+ else {
+ try {
+ var tempDate = xdr.getResponseHeader('X-Cache-Date');
+ if (tempDate && tempDate != null && tempDate.length > 0) {
+ request.lastTimestamp = tempDate.split(" ").pop();
+ }
- var tempUUID = xdr.getResponseHeader('X-Atmosphere-tracking-id');
- if (tempUUID && tempUUID != null) {
- request.uuid = tempUUID.split(" ").pop();
- }
+ var tempUUID = xdr.getResponseHeader('X-Atmosphere-tracking-id');
+ if (tempUUID && tempUUID != null) {
+ request.uuid = tempUUID.split(" ").pop();
+ }
- // HOTFIX for firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=608735
- if (request.headers) {
- jQuery.each(_request.headers, function (name) {
- var v = xdr.getResponseHeader(name);
- if (v) {
- _response.headers[name] = v;
- }
- });
+ // HOTFIX for firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=608735
+ if (request.headers) {
+ jQuery.each(_request.headers, function (name) {
+ var v = xdr.getResponseHeader(name);
+ if (v) {
+ _response.headers[name] = v;
+ }
+ });
+ }
+ } catch (e) {
}
- } catch (e) {
}
}
@@ -2325,6 +2367,7 @@ jQuery.atmosphere = function () {
f.onError(response);
break;
case "opening":
+ delete _request.closed;
if (typeof (f.onOpen) !== 'undefined')
f.onOpen(response);
break;
@@ -2341,6 +2384,7 @@ jQuery.atmosphere = function () {
f.onClientTimeout(_request);
break;
case "re-opening":
+ delete _request.closed;
if (typeof (f.onReopen) !== 'undefined')
f.onReopen(_request, response);
break;
@@ -2439,6 +2483,8 @@ jQuery.atmosphere = function () {
// Wait to be sure we have the full message before closing.
if (_response.partialMessage === "" && (rq.transport === 'streaming') && (ajaxRequest.responseText.length > rq.maxStreamingLength)) {
_response.messages = [];
+ rq.reconnectingOnLength = true;
+ rq.isReopen = true;
_invokeClose(true);
_disconnect();
_clearState();
@@ -2469,12 +2515,14 @@ jQuery.atmosphere = function () {
jQuery.ajax({
url: url,
async: false,
- timeout: _request.connectTimeout
+ timeout: _request.connectTimeout,
+ cache: false
});
} else {
jQuery.ajax({
url: url,
- async: false
+ async: false,
+ cache: false
});
}
}
@@ -2486,6 +2534,10 @@ jQuery.atmosphere = function () {
* @private
*/
function _close() {
+ if (_request.reconnectId) {
+ clearTimeout(_request.reconnectId);
+ delete _request.reconnectId;
+ }
_request.reconnect = false;
_abordingConnection = true;
_response.request = _request;
@@ -2499,6 +2551,7 @@ jQuery.atmosphere = function () {
}
function _clearState() {
+ _response.partialMessage = "";
if (_request.id) {
clearTimeout(_request.id);
}
@@ -2516,7 +2569,7 @@ jQuery.atmosphere = function () {
_activeRequest = null;
}
if (_websocket != null) {
- if (_websocket.webSocketOpened) {
+ if (_websocket.canSendMessage) {
_websocket.close();
}
_websocket = null;
@@ -2783,6 +2836,12 @@ jQuery.atmosphere = function () {
error: function () {
jQuery.atmosphere.log('error', arguments);
+ },
+
+ // TODO extract to utils or something
+ isBinary: function (data) {
+ // True if data is an instance of Blob, ArrayBuffer or ArrayBufferView
+ return /^\[object\s(?:Blob|ArrayBuffer|.+Array)\]$/.test(Object.prototype.toString.call(data));
}
};
}();
diff --git a/pom.xml b/pom.xml
index b9a3fa7c..3a4560c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
org.atmosphere
javascript-project
javascript-project
- 2.0.5-SNAPSHOT
+ 2.0.11-SNAPSHOT
pom
Javascript clients for Atmosphere