Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Socket.IO and IE8 - jsonp-polling connections always failing

Worth noting: the following is being done cross domain via https. I honestly do not think this is the issue as everything works just fine in IE10, Chrome, and FF. My guess is that it may be an XDomainRequest object variance in IE8? Not sure though.

The sendLoginRequest method below is the method called first. All the other supporting code is provided below as well.

This is all very simple, but not sure why IE8 fails as it does.

function WrappedSocket(data, session_string) {
    var clientSocket = io.connect('https://xxxxxxxx/socketio', { query: "session=" +       encodeURIComponent(session_string), transports: ['jsonp-polling'] });
    clientSocket.socket.on("connect", function () { console.log("CONNECT_SUCCEED"); });
    clientSocket.socket.on("connect_failed", function () { console.log("CONNECT_FAILED");    });
    clientSocket.socket.on("reconnect_failed", function () {    console.log("RECONNECT_FAILED"); });
    clientSocket.socket.on("error", function (eobj) { console.log("Socket error " + eobj);    });
    console.log("Made a socket that is talking");
}

var my_socket;


function set_up_socket(data, sessionString) {
    setSession(data.responseText);
    my_socket = new WrappedSocket(data, sessionString);
    my_socket.socket.emit("message", "Howdy!");
}

function sendLoginRequest(loginCode, nextRequest) {
    var xhr = createCORSRequest('POST', 'https://xxxxx/login', false);
    var sessionString = 'xxxx';

    if ("withCredentials" in xhr) {
        xhr.addEventListener("load", function () {
            set_up_socket(this, sessionString);
        }, false);
    }
    else {
        xhr.onload = function () {
            set_up_socket(this, sessionString);
        };
    }

    xhr.send();
    }

function createCORSRequest(method, url, onload) {
    xhrObj = new XMLHttpRequest();
    if ("withCredentials" in xhrObj) {
        // Check if the XMLHttpRequest object has a "withCredentials" property.
        // "withCredentials" only exists on XMLHTTPRequest2 objects. 
        if (onload) {
            xhrObj.addEventListener("load", onload, false);
        }
        xhrObj.open(method, url, true);
        xhrObj.withCredentials = true;
    } else if (typeof XDomainRequest != "undefined") {
        // Otherwise, check if XDomainRequest.
        // XDomainRequest only exists in IE, and is IE's way of making CORS requests.

        xhrObj = new XDomainRequest();
        xhrObj.open(method, url);
        if (onload) {
            xhrObj.onload = onload;
        }
    } else {
        // Otherwise, CORS is not supported by the browser.
        xhrObj = null;
    }
    return xhrObj;
    }

Errors I am seeing in both console and Fiddler Polling is in fact occurring, but the same failures keep occur on each poll:

LOG:CONNECT_FAILED
'f.parentNode' is null or not an object
'f.parentNode' is null or not an object
LOG:CONNECT_FAILED
'f.parentNode' is null or not an object
'f.parentNode' is null or not an object
LOG:CONNECT_FAILED
'f.parentNode' is null or not an object
'f.parentNode' is null or not an object
LOG:CONNECT_FAILED
'f.parentNode' is null or not an object
'f.parentNode' is null or not an object
LOG:CONNECT_FAILED
'f.parentNode' is null or not an object
'f.parentNode' is null or not an object
LOG:CONNECT_FAILED
'f.parentNode' is null or not an object
'f.parentNode' is null or not an object

............

(you get the idea, this happens over and over as it polls.)

Again, you can see each request firing through one after another, all 200 responses from the server but all results in CONNECT_FAILED and JS errors from the socket.io.js file.

Lastly, here is the code from the socket.io.js file on the client that is breaking with the errors seen above in the console screen shot ("f.parentNode is null or not an object"). I understand the object is null, what I don't get is WHY it is null.

........

if (this.isXDomain() && !io.util.ua.hasCORS) {
  var insertAt = document.getElementsByTagName('script')[0]
    , script = document.createElement('script');

  script.src = url + '&jsonp=' + io.j.length;
  insertAt.parentNode.insertBefore(script, insertAt);

  io.j.push(function (data) {
      complete(data);
      script.parentNode.removeChild(script);  // *** BREAKS HERE!! ***
  });

.........
like image 297
Jeff T Avatar asked Sep 05 '13 13:09

Jeff T


1 Answers

As per this answer, I don't believe IE8 supports the .addEventListener() method for the XMLHttpRequest() object or the XDomainRequest() (or most others, it appears to have been added later).

Try rewriting that portion of your code to:

xhr.onload=function () {
        set_up_socket(this, sessionString);
    };

If you want to keep the same syntax for other modern browsers, you could back fill by wrapping it in a conditional:

if(typeof xhr.addEventListener === undefined)
{
    xhr.onload=function () {
        set_up_socket(this, sessionString);
    };
}

Don't know if it will solve the problem, but may help.

MDN says "More recent browsers, including Firefox, also support listening to the XMLHttpRequest events via standard addEventListener APIs in addition to setting on* properties to a handler function.". Again, I'm not sure because they don't say which browsers, and when, but best I can tell IE8 does not support it.

like image 68
Jason Nichols Avatar answered Oct 30 '22 13:10

Jason Nichols