Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix #49 - Support for sockjs-client being used from pages served from…

… file:// addresses
  • Loading branch information...
commit 88375e0cbe6cd73f703d69706da1e0b173caa098 1 parent ca7b838
@majek majek authored
View
25 README.md
@@ -155,8 +155,8 @@ bad practice. If you absolutely must do it, you can use
mutliple subdomains, using different subdomain for every
SockJS connection.
-Supported transports, by browser
---------------------------------
+Supported transports, by browser (html served from http:// or https://)
+-----------------------------------------------------------------------
_Browser_ | _Websockets_ | _Streaming_ | _Polling_
----------------|------------------|-------------|-----------
@@ -182,6 +182,21 @@ Konqueror | no | no | jsonp-polling
Websockets "hixie-76". They can still be enabled by manually
changing a browser setting.
+Supported transports, by browser (html served from file://)
+-----------------------------------------------------------
+
+Sometimes you may want to serve your html from "file://" address - for
+development or if you're using PhoneGap or similar technologies. But
+due to the Cross Origin Policy files served from "file://" have no
+Origin, and that means some of SockJS transports won't work. For this
+reason the SockJS protocol table is different than usually, major
+differences are:
+
+_Browser_ | _Websockets_ | _Streaming_ | _Polling_
+----------------|---------------|--------------------|-----------
+IE 8, 9 | same as above | iframe-htmlfile | iframe-xhr-polling
+Other | same as above | iframe-eventsource | iframe-xhr-polling
+
Supported transports, by name
-----------------------------
@@ -344,12 +359,6 @@ There are various browser quirks which we don't intend to address:
that have a proper Unicode support.
* Having a global function called `onmessage` or such is probably a
bad idea, as it could be called by the built-in `postMessage` API.
- * Serving an html page that uses SockJS from `file://` url will not
- work. This is due to a badly thought through
- [CORS specification](http://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html)
- It is impossible to receive response to an Ajax request with
- cookies set (`withCredentials` set to `true`) sent from a `file://`
- origin.
* From SockJS point of view there is nothing special about
SSL/HTTPS. Connecting between unencrypted and encrypted sites
should work just fine.
View
13 lib/dom2.js
@@ -1,11 +1,11 @@
-var XHRObject = utils.XHRObject = function(method, url, payload) {
- var that = this;
- utils.delay(function(){that._start(method, url, payload);});
+var XHRObject = utils.XHRObject = function() {
+ var that = this, args = arguments;
+ utils.delay(function(){that._start.apply(that, args);});
};
XHRObject.prototype = new EventEmitter(['chunk', 'finish']);
-XHRObject.prototype._start = function(method, url, payload) {
+XHRObject.prototype._start = function(method, url, payload, opts) {
var that = this;
try {
that.xhr = new _window.ActiveXObject('Microsoft.XMLHTTP');
@@ -28,7 +28,7 @@ XHRObject.prototype._start = function(method, url, payload) {
return;
};
- if ('withCredentials' in that.xhr) {
+ if ('withCredentials' in that.xhr && (!opts || !opts.no_credentials)) {
that.xhr.withCredentials = 'true';
}
@@ -143,7 +143,8 @@ utils.isXHRCorsCapable = function() {
if (_window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()) {
return 1;
}
- if (_window.XDomainRequest) {
+ // XDomainRequest doesn't work if page is served from file://
+ if (_window.XDomainRequest && _document.domain) {
return 2;
}
if (IframeTransport.enabled()) {
View
3  lib/info.js
@@ -8,7 +8,8 @@ InfoReceiver.prototype = new EventEmitter(['finish']);
InfoReceiver.prototype.doXhr = function(base_url, AjaxObject) {
var that = this;
var t0 = (new Date()).getTime();
- var xo = new AjaxObject('GET', base_url + '/info' , null);
+ var xo = new AjaxObject('GET', base_url + '/info', null,
+ {no_credentials: true});
var tref = utils.delay(8000,
function(){xo.ontimeout();});
View
1  lib/sockjs.js
@@ -233,6 +233,7 @@ SockJS.prototype._applyInfo = function(info, rtt, protocols_whitelist) {
that._options.info = info;
that._options.rtt = rtt;
that._options.rto = utils.countRTO(rtt);
+ that._options.info.null_origin = !_document.domain;
var probed = utils.probeProtocols();
that._protocols = utils.detectProtocols(probed, protocols_whitelist, info);
};
View
22 lib/utils.js
@@ -283,21 +283,27 @@ utils.detectProtocols = function(probed, protocols_whitelist, info) {
}
// 2. Streaming
- if (pe['xdr-streaming'] && !info.cookie_needed) {
+ if (pe['xdr-streaming'] && !info.cookie_needed && !info.null_origin) {
protocols.push('xdr-streaming');
} else {
- maybe_push(['xhr-streaming',
- 'iframe-eventsource',
- 'iframe-htmlfile']);
+ if (pe['xhr-streaming'] && !info.null_origin) {
+ protocols.push('xhr-streaming');
+ } else {
+ maybe_push(['iframe-eventsource',
+ 'iframe-htmlfile']);
+ }
}
// 3. Polling
- if (pe['xdr-polling'] && !info.cookie_needed) {
+ if (pe['xdr-polling'] && !info.cookie_needed && !info.null_origin) {
protocols.push('xdr-polling');
} else {
- maybe_push(['xhr-polling',
- 'iframe-xhr-polling',
- 'jsonp-polling']);
+ if (pe['xhr-polling'] && !info.null_origin) {
+ protocols.push('xhr-polling');
+ } else {
+ maybe_push(['iframe-xhr-polling',
+ 'jsonp-polling']);
+ }
}
return protocols;
}
View
15 tests/html/src/unittests.coffee
@@ -177,6 +177,21 @@ test 'detectProtocols', ->
deepEqual(u.detectProtocols(ie8_probed, null, {cookie_needed:true}),
['iframe-htmlfile', 'iframe-xhr-polling'])
+ # Check if protocols are picked up correctly when served from file://
+ deepEqual(u.detectProtocols(chrome_probed, null, {null_origin:true}),
+ ['websocket', 'iframe-eventsource', 'iframe-xhr-polling'])
+ deepEqual(u.detectProtocols(chrome_probed, null,
+ {websocket:false, null_origin:true}),
+ ['iframe-eventsource', 'iframe-xhr-polling'])
+
+ deepEqual(u.detectProtocols(opera_probed, null, {null_origin:true}),
+ ['iframe-eventsource', 'iframe-xhr-polling'])
+
+ deepEqual(u.detectProtocols(ie6_probed, null, {null_origin:true}),
+ ['jsonp-polling'])
+ deepEqual(u.detectProtocols(ie8_probed, null, {null_origin:true}),
+ ['iframe-htmlfile', 'iframe-xhr-polling'])
+
test "EventEmitter", ->
expect(4)
r = new SockJS('//wrongdomainthatdoesntresolveatall/abc', null,
Please sign in to comment.
Something went wrong with that request. Please try again.