Ad

Firefox Randomly Close XMLHttpRequest Connection If Inactive. Why?

- 1 answer

In a JavaScript class, an XMLHttpRequest connect to the server. The server is sending data, slowly. This work fine in Chromium, but Firefox close the connection after random time (between ~4s and ~70s).

Why Firefox close the connection? and How to avoid that?

Simplified JS code:

    var options = {};
    options['header']=
        { 'Cache-Control':'no-cache, max-age=0', 
            'Content-type': 'application/octet-stream',
            'Content-Disposition': 'inline'
        };

    // Get request information
    this.http = new XMLHttpRequest();
    this.http.onreadystatechange = _streamingResponse.bind(this);
    this.http.open('post', url, true);
    for (var i in options['header'])
    {
        this.http.setRequestHeader(i, options['header'][i]);
    }
    this.http.send('');

for the PHP part, something like:

sleep(200); //wait long time, so firefox close the socket.

If the server send something every few seconds (<5s) the connection stay alive "forever". But if no data is sent, Firefox close the connection.

The connection close with: - readyState = 4 - status = 0

The server seem to be correct, as in Chromium it work correctly.

Full test code:

test.html

<html>
<header>
</header>
<body>
</body>

<script type="application/javascript">

    function log( msg )
    {
        document.body.appendChild(document.createElement('div').appendChild(document.createTextNode(msg)));
        document.body.appendChild(document.createElement('br'));
    }

    function request(url)
    {
        function _streamingResponse()
        {
            if (4==this.http.readyState)
            {
                log('Done: ' + this.http.status);
            }
            else if (3==this.http.readyState)
            {
                var text = this.http.response.substr(this.lastRequestPos);
                this.lastRequestPos = this.http.response.length;
                log('Update: ' + text);
            }
        }

        var options = {};
        options['header']=
            { 'Cache-Control':'no-cache, max-age=0', 
                'Content-type': 'application/octet-stream',
                'Content-Disposition': 'inline'
            };

        this.lastRequestPos=0;

        // Get request information
        this.http = new XMLHttpRequest();
        this.http.onreadystatechange = _streamingResponse.bind(this);
        this.http.open('post', url, true);
        for (var i in options['header'])
        {
            this.http.setRequestHeader(i, options['header'][i]);
        }
        this.http.send('');
        log('Request sent!');
    }

    req = new request('./test.php');
</script>
</html>

test.php

<?php

$timer = 60;

ignore_user_abort(true);
set_time_limit(0);

// Turn off output buffering and compression
ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
ini_set('implicit_flush', true);
ob_implicit_flush(true);
while (ob_get_level() > 0) {
    $level = ob_get_level();
    ob_end_clean();
    if (ob_get_level() == $level) break;
}
if (function_exists('apache_setenv')) {
    apache_setenv('no-gzip', '1');
    apache_setenv('dont-vary', '1');
}

// Set header for streaming
header('Content-type: application/octet-stream');
flush();

// Send information
sleep($timer);
echo '<yes></yes>';
flush();

?>

Additional note: Firefox 43.0.03, Chromium 47.0.2526

EDITED:

Setting a callback for timeout it do not trigger. I conclude it is not a timeout.

this.http.timeout = 2000;
this.http.ontimeout = _streamingTimeout.bind(this);
Ad

Answer

After searching further, I found a Bug in Mozilla which seem the responsible of this behaviour. It should be solved in the version 45, but until then, we have to lead with it.

Even if the bug seem related only to Ipv6, I have the same issue using 127.0.0.1. However, with Firefox Developer Edition (V 45) the problem seem solved.

Why Firefox close the connection?

It should not. ref: https://bugzilla.mozilla.org/show_bug.cgi?id=1240319

How to solve it?

Except to send data every 3-4 seconds to maintain the connection open, I have no idea.

Ad
source: stackoverflow.com
Ad