| 233 | |
| 234 | |
| 235 | class ConfigApp(tornado.web.Application): |
| 236 | |
| 237 | def __init__(self): |
| 238 | # generate a new auth token using UUID |
| 239 | self.access_token = uuid.uuid4().hex |
| 240 | settings = { |
| 241 | "access_token": self.access_token, # our custom setting |
| 242 | "login_url": "/version", |
| 243 | "debug": True |
| 244 | } |
| 245 | handlers = [ |
| 246 | (r"/(.*\.html)", tornado.web.StaticFileHandler, {"path": current_dir}), |
| 247 | (r"/((css|images|js|fonts)/.*)", tornado.web.StaticFileHandler, {"path": current_dir}), |
| 248 | (r"/(version.txt)", tornado.web.StaticFileHandler, {"path": os.path.join(current_dir, "../../../")}), |
| 249 | (r"/config", ConfigHandler), # main configuration handler |
| 250 | (r"/user_phrases", UserPhraseHandler), # user phrase editor |
| 251 | (r"/user_phrase_file", UserPhraseFileHandler), # export user phrase |
| 252 | (r"/keep_alive", KeepAliveHandler), # keep the api server alive |
| 253 | (r"/login/(.*)", LoginHandler), # authentication |
| 254 | ] |
| 255 | super().__init__(handlers, **settings) |
| 256 | self.timeout_handler = None |
| 257 | self.port = 0 |
| 258 | |
| 259 | def launch_browser(self, tool_name): |
| 260 | user_html = """<html> |
| 261 | <form id="auth" action="http://127.0.0.1:{PORT}/login/{PAGE_NAME}" method="POST"> |
| 262 | <input type="hidden" name="token" value="{TOKEN}"> |
| 263 | </form> |
| 264 | <script type="text/javascript"> |
| 265 | document.getElementById("auth").submit(); |
| 266 | </script> |
| 267 | </html>""".format(PORT=self.port, PAGE_NAME=tool_name, TOKEN=self.access_token) |
| 268 | # use a local html file to send access token to our service via http POST for authentication. |
| 269 | os.makedirs(localdata_dir, exist_ok=True) |
| 270 | filename = os.path.join(localdata_dir, "launch_{}.html".format(tool_name)) |
| 271 | with open(filename, "w") as f: |
| 272 | f.write(user_html) |
| 273 | os.startfile(filename) |
| 274 | |
| 275 | def run(self, tool_name): |
| 276 | # find a port number that's available |
| 277 | random.seed() |
| 278 | while True: |
| 279 | port = random.randint(1025, 65535) |
| 280 | try: |
| 281 | self.listen(port, "127.0.0.1") |
| 282 | break |
| 283 | except OSError: # it's possible that the port we want to use is already in use |
| 284 | continue |
| 285 | self.port = port |
| 286 | |
| 287 | self.launch_browser(tool_name) |
| 288 | |
| 289 | # setup the main event loop |
| 290 | loop = tornado.ioloop.IOLoop.current() |
| 291 | self.timeout_handler = loop.call_later(SERVER_TIMEOUT, self.quit) |
| 292 | loop.start() |