lwzm
11/30/2019 - 10:46 AM

notice.py

#!/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()