#!/usr/bin/perl -- # IE streaming server-push problem demonstration ##################### +########## ###################################################################### +########## # This script is meant to demonstrate strange IE behavior when working + with # streaming data. When directed to http://localhost:9090/, the browse +r should # print a page which simply displays the following: # # Awaiting commands... # Connecting... (script should start alerting soon) # Executing command: alert('a' + 0) # Executing command: alert('b' + 0) # Executing command: alert('c' + 1) # Disconnected. # Connecting... (script should start alerting soon) # # Each command should be accompanied by an alert box with the specifie +d message. # The script should print these messages in Firefox, but in Internet E +xplorer, # the printing of Executing command: is not expected to occur since IE + is not # expected to allow access to the responseText until the server has cl +osed the # socket. It /should/, however, signal alerts, but this is not happen +ing. # # After the server prints the three commands, it closes the socket. T +he # client re-establishes the connection and it begins again. Only at t +his point # does IE print the alert messages. use IO::Socket; use strict; $| = 1; my $sock = new IO::Socket::INET( LocalPort => 9090, Proto => 'tcp', Listen => SOMAXCONN, Reuse => 1 ); while (my $client = $sock->accept) { print "\nReceived a connection\n"; my $request = <$client>; # PRINT THE COMET SCRIPT SNIPPETS ################################## +########## # This code is run when connecting to localhost:9090/?ajax if ($request =~ /comet/) { print $client "HTTP/1.0 200 OK\nContent-type: text/html\n\n"; $_ = int(rand() * 5); print "a $_\n"; print $client "<script>alert('a ' + $_)</script>\n"; sleep(2); # wait 2 seconds $_ = int(rand() * 5); print "b $_\n"; print $client "<script>alert('b ' + $_)</script>\n"; sleep(2); # wait 2 seconds $_ = int(rand() * 5); print "c $_\n"; print $client "<script>alert('c ' + $_)</script>\n"; } # PRINT THE HTML PAGE ############################################## +########## # This code is run when connecting to localhost:9090 else { print $client "HTTP/1.0 200 OK\nContent-type: text/html\n\n"; print $client qq{ <html> <body> <input type="button" value="Stop connection attempts" onclick="recon +nect = 0;"> <div id="status"> Awaiting commands...<br> </div> <script> // Change the server address here if you cannot use localhost:9090 var server = 'http://localhost:9090/'; var interval = 0; var status = document.getElementById('status'); var pos = 0; var reconnect = 1; // Adapted from http://empireenterprises.com/_comet.html // Removed Opera support for this demo function connect() { status.innerHTML += 'Connecting... (script should start alerting + soon)<br>'; pos = 0; // Internet Explorer (just a quick IE vs FF check) if (document.all) { // By creating a new ActiveXObject('htmlfile'), there is no lo +ad bar. var doc = new ActiveXObject('htmlfile'); doc.open(); doc.write('<html>'); doc.write('<html>'); doc.write('<script>document.domain = \\'' + document.domain + +'\\''); doc.write('</html>'); doc.close(); var div = doc.createElement('DIV'); doc.appendChild(div); // This /should/ just run the Javascript commands as it receiv +es them, // but unfortunately it is not. div.innerHTML = '<iframe name=\\'ifr\\' src=\\'' + server + '/ +?comet\\'></iframe>'; // It should not be useful to poll the iframe. From what I un +derstand // about IE, the content WILL NOT be available until the DOM i +s // complete. Unfortunately that doesn't happen when streaming +. // Hence, the messages are printed as <script> tags because I // believe that somehow (perhaps if the message is printed /ju +st right/) // that IE will actually call the Javascript functions as it r +eceives // them. // Nevertheless, I am leaving this code in because it is also +in the // example. if(!interval) { interval = setInterval( function() { var xmlhttp = doc.frames['ifr'].document; if(xmlhttp.readyState == 'complete') { clearInterval(interval); interval = false; status.innerHTML += 'Disconnected.<br>'; if (reconnect) connect(); } var data; try { data = xmlhttp.firstChild.innerHTML; } catch(error) { return; } data = data.substring(pos); if(data.indexOf('<SCRIPT>') < 0) { return; } var start = data.indexOf('<SCRIPT>') + 8; var stop = data.indexOf('<\\/SCRIPT>') - start; data = data.substr(start, stop); try { // Uncomment these two lines to see that IE only recei +ves the // innerHTML after the server closes the socket. //status.innerHTML += ' Executing command +: ' + data.replace(/</g,'<') + '<br>'; //eval(data); } catch(error) { } pos += start + 8 + stop - 1; }, 500 ); } } // Firefox. Opera implementation works, too - it just isn't inc +luded // (use an interval to poll xmlhttp.responseText) else { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if(xmlhttp.readyState == 4) { status.innerHTML += 'Disconnected.<br>'; if (reconnect) connect(); return false; } if(xmlhttp.readyState == 3) { var data = xmlhttp.responseText; data = data.substr(pos); if(data.indexOf('<script>') < 0) { return(false); } var start = data.indexOf('<script>') + 8; var stop = data.indexOf('<\\/script>') - start; data = data.substr(start, stop); status.innerHTML += ' Executing command: ' ++ data.replace(/</g,'<') + '<br>'; try { eval(data); } catch(error) { } pos += start + 8 + stop; } }; xmlhttp.open('GET', server + '/?comet', true); xmlhttp.send(''); } } connect(); </script> </body> </html> }; close o; } close $client; } 1;
In reply to Streaming JS commands to IE with a Perl HTTP push server by freefall
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |