import tornado.ioloop import tornado.web import tornado.websocket import logging import coloredlogs import argparse import json from urllib.parse import urlparse logger = logging.getLogger("drawing") argParser = argparse.ArgumentParser(description='Start up the server to have non-Mechanical Turks draw their sketches.') argParser.add_argument( '--port', '-p', default=8888, help='The port for the server to listen' ) argParser.add_argument( '--verbose', '-v', action="store_true", ) class StaticFileWithHeaderHandler(tornado.web.StaticFileHandler): def set_extra_headers(self, path): """For subclass to add extra headers to the response""" if path[-5:] == '.html': self.set_header("Access-Control-Allow-Origin", "*") class WebSocketHandler(tornado.websocket.WebSocketHandler): CORS_ORIGINS = ['localhost', '.mturk.com'] connections = set() def check_origin(self, origin): parsed_origin = urlparse(origin) # parsed_origin.netloc.lower() gives localhost:3333 valid = any([parsed_origin.hostname.endswith(origin) for origin in self.CORS_ORIGINS]) return valid # the client connected def open(self, p = None): self.__class__.connections.add(self) logger.info("New client connected") self.write_message("hello!") # the client sent the message def on_message(self, message): logger.debug(f"recieve: {message}") try: msg = json.loads(message) if msg['action'] == 'move': pass elif msg['action'] == 'up': logger.info(f'up: {msg}') elif msg['action'] == 'submit': logger.info(f'up: {msg}') self.write_message(json.dumps('submitted')) elif msg['action'] == 'down': # not used, implicit in move? pass else: # self.send({'alert': 'Unknown request: {}'.format(message)}) logger.warn('Unknown request: {}'.format(message)) except Exception as e: # self.send({'alert': 'Invalid request: {}'.format(e)}) logger.exception(e) # client disconnected def on_close(self): self.__class__.rmConnection(self) logger.info("Client disconnected") @classmethod def rmConnection(cls, client): if client not in cls.connections: return cls.connections.remove(client) if __name__ == "__main__": args = argParser.parse_args() print(logger.level) coloredlogs.install( level=logging.DEBUG if args.verbose else logging.INFO, ) logger.addHandler( logging.handlers.RotatingFileHandler( 'mt_server.log', maxBytes=1024*512, backupCount=5 ) ) application = tornado.web.Application([ (r"/ws(.*)", WebSocketHandler), (r"/(.*)", StaticFileWithHeaderHandler, {"path": 'www', "default_filename": 'index.html'}), ], debug=True) application.listen(args.port) tornado.ioloop.IOLoop.current().start()