#!/usr/bin/env python3
import asyncio
import collections
import tornado.web
class Base(tornado.web.RequestHandler):
_futures = collections.defaultdict(set)
def set_default_headers(self):
self.clear_header("Content-Type")
self.clear_header("Server")
def compute_etag(self):
return None
def on_connection_close(self):
try:
key, future = self._future_todo
except AttributeError:
return
self._futures[key].discard(future)
future.cancel()
@classmethod
def complete(cls, key, msg, all=False):
todos = cls._futures[key]
if not todos:
return 0
if not all:
todos.pop().set_result(msg)
return 1
n = len(todos)
for i in todos:
i.set_result(msg)
todos.clear()
return n
def promise(self, key):
future = asyncio.Future()
self._futures[key].add(future)
self._future_todo = key, future
return future
class Handler(Base):
async def get(self, key):
try:
mime, payload = await self.promise(key)
except asyncio.CancelledError:
raise tornado.web.HTTPError(408)
mime and self.set_header("Content-Type", mime)
self.write(payload)
def post(self, key):
flag = self.get_query_argument("all", None) is not None
mime = self.request.headers.get('Content-Type')
msg = mime, self.request.body
n = self.complete(key, msg, flag)
self.write(str(n))
app = tornado.web.Application([
(r"/(.*)", Handler),
])
if __name__ == "__main__":
from tornado.options import parse_command_line
from tornado.ioloop import IOLoop
parse_command_line()
app.listen(1111, xheaders=True)
IOLoop.current().start()