I have a simple comet server in written in Twisted. It prints out time stamps. I also have a small static webserver running on the same port. The javascript on the page served tries to update the page by appending the timestamps from the comet server.
But nothing is displayed from the comet server. Using the developer tools in Chromium, I can see that a long connection is opened. But the connection times out and nothing is appended to the page. Why doesn’t it work?
Here’s a self-contained example:
from twisted.internet import reactor
from twisted.internet import task
from twisted.web import server
from twisted.web.server import Site
from twisted.web.resource import Resource
import time
class ClockPage(Resource):
isLeaf = True
def __init__(self):
self.presence=[]
loopingCall = task.LoopingCall(self._print_time)
loopingCall.start(1, False)
Resource.__init__(self)
def render_GET(self, request):
# The browser won't display any output until it's gotten a minimum
# number of bytes from the server or something. Hence, junk divs.
request.write('''<div class="11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"></div><div class="111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111187348937284789374872387847847811111111111111723872187383738271893789217387389737389711111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"></div>''')
request.write('<b>%s</b><br>' % (time.ctime(),))
self.presence.append(request)
return server.NOT_DONE_YET
def _print_time(self):
for p in self.presence:
p.write('<b>%s</b><br>' % (time.ctime(),))
class UpdatePage(Resource):
def render_GET(self, request):
return """
<!doctype html>
<html>
<head>
<title>Metastatus</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js";></script>
<script type="text/javascript">
function addentry(type, msg) {
"use strict";
if (type === "new" && msg !== "") {
$("#entries").prepend(
"<li>" + msg + "</li>"
);
}
}
function waitForMsg() {
"use strict";
$.ajax({
type: "GET",
url: "http://localhost:8080/clock",
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout: 50000, /* Timeout in ms */
success: function (data) { /* called when request to barge.php completes */
addentry("new", data); /* Add response to a .msg div (with the "new" class)*/
setTimeout(
waitForMsg(), /* Request next message */
1000 /* ..after 1 seconds */
);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
addentry("error", textStatus + " (" + errorThrown + ")");
setTimeout(
waitForMsg(), /* Try again after.. */
"15000"
); /* milliseconds (15seconds) */
}
});
}
$(document).ready(function () {
"use strict";
waitForMsg(); /* Start the inital request */
});
</script>
</head>
<body>
<h1>Example</h1>
<ul id="entries"></ul>
</body>
</html>"""
if __name__ == '__main__':
root = Resource()
root.putChild('', UpdatePage())
root.putChild('clock', ClockPage())
factory = Site(root)
reactor.listenTCP(8080, factory)
reactor.run()
You can’t rely on getting response data in JavaScript until the response is fully delivered to the client. This behavior varies from browser to browser, so you will see it work as you want sometimes, and not work at all other times.
You also can’t rely on connections remaining open indefinitely, largely due to HTTP proxies between the browser and your server.