inkstitch/lib/api/server.py

120 wiersze
3.4 KiB
Python
Czysty Zwykły widok Historia

2021-03-12 04:17:19 +00:00
# Authors: see git history
#
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
2020-04-28 16:34:05 +00:00
import errno
import logging
import socket
import sys
2020-04-28 16:34:05 +00:00
import time
from threading import Thread
2020-04-28 16:34:05 +00:00
import requests
2021-07-29 16:16:06 +00:00
from flask import Flask, g
from werkzeug.serving import make_server
2020-04-28 16:34:05 +00:00
from ..utils.json import InkStitchJSONEncoder
from .install import install
2020-04-28 16:34:05 +00:00
from .simulator import simulator
from .stitch_plan import stitch_plan
class APIServer(Thread):
def __init__(self, *args, **kwargs):
self.extension = args[0]
Thread.__init__(self, *args[1:], **kwargs)
self.daemon = True
self.app = None
self.host = None
self.port = None
self.ready = False
self.__setup_app()
2021-07-29 16:16:06 +00:00
self.flask_server = None
self.server_thread = None
2020-04-28 16:34:05 +00:00
def __setup_app(self): # noqa: C901
# Disable warning about using a development server in a production environment
cli = sys.modules['flask.cli']
cli.show_server_banner = lambda *x: None
2020-04-28 16:34:05 +00:00
self.app = Flask(__name__)
self.app.json_encoder = InkStitchJSONEncoder
self.app.register_blueprint(simulator, url_prefix="/simulator")
self.app.register_blueprint(stitch_plan, url_prefix="/stitch_plan")
self.app.register_blueprint(install, url_prefix="/install")
2020-04-28 16:34:05 +00:00
@self.app.before_request
def store_extension():
# make the InkstitchExtension object available to the view handling
# this request
g.extension = self.extension
@self.app.route('/ping')
def ping():
return "pong"
def stop(self):
2021-07-29 16:16:06 +00:00
self.flask_server.shutdown()
self.server_thread.join()
2020-04-28 16:34:05 +00:00
def disable_logging(self):
logging.getLogger('werkzeug').setLevel(logging.ERROR)
def run(self):
self.disable_logging()
self.host = "127.0.0.1"
self.port = 5000
while True:
try:
2021-07-29 16:16:06 +00:00
self.flask_server = make_server(self.host, self.port, self.app)
self.server_thread = Thread(target=self.flask_server.serve_forever)
self.server_thread.start()
2020-04-28 16:34:05 +00:00
except socket.error as e:
if e.errno == errno.EADDRINUSE:
self.port += 1
continue
else:
raise
else:
break
def ready_checker(self):
"""Wait until the server is started.
Annoyingly, there's no way to get a callback to be run when the Flask
server starts. Instead, we'll have to poll.
"""
while True:
if self.port:
try:
response = requests.get("http://%s:%s/ping" % (self.host, self.port))
if response.status_code == 200:
break
except socket.error as e:
2020-04-28 16:34:05 +00:00
if e.errno == errno.ECONNREFUSED:
pass
else:
raise
time.sleep(0.1)
def start_server(self):
"""Start the API server.
returns: port (int) -- the port that the server is listening on
(on localhost)
"""
checker = Thread(target=self.ready_checker)
checker.start()
self.start()
checker.join()
return self.port