When working with a JavaScript class, an XMLHttpRequest is used to connect to the server. The server sends data slowly, and this process functions well in Chromium. However, Firefox tends to close the connection randomly after a certain amount of time (typically between approximately 4 seconds and 70 seconds).
What could be causing Firefox to close the connection, and how can this issue be prevented?
Here is a simplified version of the JS code being used:
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 component, something like this may occur:
sleep(200); //wait for a long time, resulting in Firefox closing the socket.
If the server sends data every few seconds (less than 5 seconds), the connection remains active indefinitely. However, if no data is transmitted, Firefox closes the connection.
The connection closure details are as follows: - readyState = 4 - status = 0
The server appears to function correctly since it works as expected in Chromium.
Complete 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 does not seem to trigger. I have concluded that it is not necessarily a timeout issue.
this.http.timeout = 2000;
this.http.ontimeout = _streamingTimeout.bind(this);