[Pkg-javascript-commits] [sockjs-client] 114/434: Enable chunking-detection for streaming protocols (with the exception of websockets).

Tonnerre Lombard tonnerre-guest at moszumanska.debian.org
Wed Jan 8 00:47:07 UTC 2014


This is an automated email from the git hooks/post-receive script.

tonnerre-guest pushed a commit to branch master
in repository sockjs-client.

commit 023cb6ab2fd6e8d59d1036a5df146919f10a4bc4
Author: Marek Majkowski <majek04 at gmail.com>
Date:   Thu Sep 1 17:30:53 2011 +0100

    Enable chunking-detection for streaming protocols (with the exception of websockets).
    
    It's possible that some users will be behind a broken proxy that doesn't allow chunking protocols. Instead of handling this problem in every streaming protocol manually (like previously we did for xhr-polling/streaming), we will run a single test that ought to detect if chunking works at all. The underlying assumption is that if chunking works for XHR protocol, it is likely that it will work for htmlfile and eventsource.
---
 lib/chunking-test.js            | 82 +++++++++++++++++++++++++++++++++++++++++
 lib/index.js                    |  1 +
 lib/sockjs.js                   | 23 ++++++++++--
 lib/trans-iframe-eventsource.js |  2 +
 lib/trans-iframe-htmlfile.js    |  2 +
 lib/trans-receiver-xhr.js       | 10 ++++-
 lib/trans-xhr-streaming.js      |  2 +
 7 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/lib/chunking-test.js b/lib/chunking-test.js
new file mode 100644
index 0000000..c6937bf
--- /dev/null
+++ b/lib/chunking-test.js
@@ -0,0 +1,82 @@
+var doChunkingTest = function(base_url, callback, cors) {
+    var recv = new XhrReceiver(base_url + '/chunking_test', {cors: cors});
+    var chunk_nos = {};
+    recv.onmessage = function(e) {
+        chunk_nos[e.chunk_no] = true;
+        // Now a cool hack: we can stop receiving after we got more
+        // than one chunk:
+        if (utils.objectLength(chunk_nos) > 1) {
+            recv.abort();
+        }
+    };
+    recv.onclose = function(e) {
+        recv = recv.onmessage = recv.onclose = null;
+        var l = utils.objectLength(chunk_nos);
+        utils.log('Chunking test: ' + (l > 1 ? 'passed' : 'failed')
+                  + ' (' + l + ' chunks received)');
+        callback(l > 1);
+    };
+};
+
+var ChunkingTestIframe = FacadeJS['w-iframe-chunking-test'] = function (ri, trans_url, base_url) {
+    doChunkingTest(base_url, function(r) {
+                       ri._didMessage('m'+r);
+                       ri._didClose();
+                   }, false);
+};
+ChunkingTestIframe.prototype.doCleanup = function() {};
+
+var chunkingTestUncached = function(base_url, callback) {
+    // 1. CORS
+    if (_window.XDomainRequest ||
+         (_window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest())) {
+        doChunkingTest(base_url, callback, true);
+        return;
+    }
+    // 2. Iframe
+    if (IframeTransport.enabled()) {
+        var ifr = new IframeTransport();
+        ifr.protocol = 'w-iframe-chunking-test';
+        var mock_ri = {
+            _options: {},
+            _didClose: function() {},
+            _didMessage: function(r) {
+                if(r.slice(0,1) === 'm') {
+                    callback(r.slice(1));
+                }
+                ifr.doCleanup();
+            }
+        };
+        ifr.i_constructor(mock_ri, '', base_url);
+        return;
+    }
+    // 3. Fall back to polling (IE 7)
+    setTimeout(function() {
+                   callback(false);
+               }, 0);
+    return;
+};
+
+// Although chunking test is run against a particular 'base_url', it's
+// safe to assume that if chunking works for client, it will work for
+// any SockJS server. That means we can cache the result of
+// chunkingTest, at least until user switches network. Let's assume a
+// value of 10 seconds.
+var chunkingTest = function() {
+    var value;
+    var t0 = 0;
+    return function (base_url, callback) {
+        var t1 = (new Date()).getTime();
+        if (t1 - t0 > 10000) {
+            chunkingTestUncached(base_url, function (v) {
+                                     value = v;
+                                     t0 = (new Date()).getTime();
+                                     callback(value);
+                                 });
+        } else {
+            setTimeout(function() {
+                           callback(value);
+                       }, 0);
+        }
+    };
+}();
diff --git a/lib/index.js b/lib/index.js
index ad1b2f2..ee2e3e1 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -14,6 +14,7 @@ SockJS = (function(){
 <!-- include lib/trans-xhr-polling.js -->
 <!-- include lib/trans-iframe.js -->
 <!-- include lib/trans-iframe-within.js -->
+<!-- include lib/chunking-test.js -->
 <!-- include lib/trans-iframe-eventsource.js -->
 <!-- include lib/trans-iframe-xhr-polling.js -->
 <!-- include lib/trans-iframe-htmlfile.js -->
diff --git a/lib/sockjs.js b/lib/sockjs.js
index dd8bc79..dca1950 100644
--- a/lib/sockjs.js
+++ b/lib/sockjs.js
@@ -1,6 +1,6 @@
 var SockJS = function(url, protocols, options) {
     var that = this;
-    that._options = {devel: false, debug: false};
+    that._options = {devel: false, debug: false, chunking: undefined};
     if (options) {
         utils.objectExtend(that._options, options);
     }
@@ -131,15 +131,32 @@ SockJS.prototype._didMessage = function(data) {
 
 SockJS.prototype._try_next_protocol = function(close_event) {
     var that = this;
-    if (that.protocol)
+    if (that.protocol) {
         that._debug('Closed transport:', that.protocol, ''+close_event);
+        that.protocol = null;
+    }
+
+    // Some protocols require chunking, we may need to run the test beforehand.
+    var protocol = that._protocols[0];
+    if (protocol && SockJS[protocol] &&
+          SockJS[protocol].need_chunking === true &&
+          that._options.chunking === undefined) {
+        chunkingTest(that._base_url, function(chunking) {
+                         that._options.chunking = chunking;
+                         that._try_next_protocol();
+                     });
+        return true;
+    }
 
     while(1) {
         that.protocol = that._protocols.shift();
         if (!that.protocol) {
             return false;
         }
-        if (!SockJS[that.protocol] || !SockJS[that.protocol].enabled(that._options)) {
+        if (!SockJS[that.protocol] ||
+              (SockJS[that.protocol].need_chunking === true &&
+                   that._options.chunking !== true) ||
+              !SockJS[that.protocol].enabled(that._options)) {
             that._debug('Skipping transport:', that.protocol);
         } else {
             that._debug('Opening transport:', that.protocol);
diff --git a/lib/trans-iframe-eventsource.js b/lib/trans-iframe-eventsource.js
index bc6073e..10ca71c 100644
--- a/lib/trans-iframe-eventsource.js
+++ b/lib/trans-iframe-eventsource.js
@@ -11,6 +11,8 @@ EventSourceIframeTransport.enabled = function () {
     return (typeof EventSource === 'function') && IframeTransport.enabled();
 };
 
+EventSourceIframeTransport.need_chunking = true;
+
 
 var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function (ri, trans_url) {
     var that = this;
diff --git a/lib/trans-iframe-htmlfile.js b/lib/trans-iframe-htmlfile.js
index abdbccc..45ba270 100644
--- a/lib/trans-iframe-htmlfile.js
+++ b/lib/trans-iframe-htmlfile.js
@@ -18,6 +18,8 @@ HtmlFileIframeTransport.enabled = function (options) {
     return (options.devel || ie) && IframeTransport.enabled();
 };
 
+HtmlFileIframeTransport.need_chunking = true;
+
 
 var HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function (ri, trans_url) {
     var that = this;
diff --git a/lib/trans-receiver-xhr.js b/lib/trans-receiver-xhr.js
index 9420d51..14a3a94 100644
--- a/lib/trans-receiver-xhr.js
+++ b/lib/trans-receiver-xhr.js
@@ -2,10 +2,12 @@
 var XhrReceiver = function(url, opts) {
     var that = this;
     var buf_pos = 0;
+    var chunk_no = 0;
     var orsc = function (xhr, e, abort_reason) {
         if (xhr.readyState === 3 || xhr.readyState === 4) {
+            chunk_no += 1;
             // IE doesn't like peeking into responseText or status on
-            // readystate=3
+            // XHR and readystate=3
             try {
                 var responseText = xhr.responseText;
                 var status = xhr.status;
@@ -18,7 +20,11 @@ var XhrReceiver = function(url, opts) {
                     if (p === -1) break;
                     buf_pos += p+1;
                     var msg = buf.slice(0, p);
-                    that.dispatchEvent(new SimpleEvent('message', {'data': msg}));
+                    that.dispatchEvent(
+                        new SimpleEvent('message', {
+                                            data: msg,
+                                            chunk_no: chunk_no
+                                        }));
                 }
             }
         }
diff --git a/lib/trans-xhr-streaming.js b/lib/trans-xhr-streaming.js
index f1a8850..7348f5e 100644
--- a/lib/trans-xhr-streaming.js
+++ b/lib/trans-xhr-streaming.js
@@ -29,3 +29,5 @@ XhrStreamingTransport.enabled = function(options) {
     return false;
 };
 
+XhrStreamingTransport.need_chunking = true;
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/sockjs-client.git



More information about the Pkg-javascript-commits mailing list