REST-JSON API server
(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=RESTAPI_DEFAULT_ADAPTER, username=None, password=None, database=None)
| 681 | return jsonize({"success": True, "version": VERSION_STRING.split('/')[-1]}) |
| 682 | |
| 683 | def server(host=RESTAPI_DEFAULT_ADDRESS, port=RESTAPI_DEFAULT_PORT, adapter=RESTAPI_DEFAULT_ADAPTER, username=None, password=None, database=None): |
| 684 | """ |
| 685 | REST-JSON API server |
| 686 | """ |
| 687 | |
| 688 | DataStore.admin_token = encodeHex(os.urandom(16), binary=False) |
| 689 | DataStore.username = username |
| 690 | DataStore.password = password |
| 691 | |
| 692 | if not database: |
| 693 | _, Database.filepath = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.IPC, text=False) |
| 694 | os.close(_) |
| 695 | else: |
| 696 | Database.filepath = database |
| 697 | |
| 698 | if port == 0: # random |
| 699 | with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s: |
| 700 | s.bind((host, 0)) |
| 701 | port = s.getsockname()[1] |
| 702 | |
| 703 | logger.info("Running REST-JSON API server at '%s:%d'.." % (host, port)) |
| 704 | logger.info("Admin (secret) token: %s" % DataStore.admin_token) |
| 705 | logger.debug("IPC database: '%s'" % Database.filepath) |
| 706 | |
| 707 | # Initialize IPC database |
| 708 | DataStore.current_db = Database() |
| 709 | DataStore.current_db.connect() |
| 710 | DataStore.current_db.init() |
| 711 | |
| 712 | # Run RESTful API |
| 713 | try: |
| 714 | # Supported adapters: aiohttp, auto, bjoern, cgi, cherrypy, diesel, eventlet, fapws3, flup, gae, gevent, geventSocketIO, gunicorn, meinheld, paste, rocket, tornado, twisted, waitress, wsgiref |
| 715 | # Reference: https://bottlepy.org/docs/dev/deployment.html || bottle.server_names |
| 716 | |
| 717 | if adapter == "gevent": |
| 718 | from gevent import monkey |
| 719 | monkey.patch_all() |
| 720 | elif adapter == "eventlet": |
| 721 | import eventlet |
| 722 | eventlet.monkey_patch() |
| 723 | logger.debug("Using adapter '%s' to run bottle" % adapter) |
| 724 | run(host=host, port=port, quiet=True, debug=True, server=adapter) |
| 725 | except socket.error as ex: |
| 726 | if "already in use" in getSafeExString(ex): |
| 727 | logger.error("Address already in use ('%s:%s')" % (host, port)) |
| 728 | else: |
| 729 | raise |
| 730 | except ImportError: |
| 731 | if adapter.lower() not in server_names: |
| 732 | errMsg = "Adapter '%s' is unknown. " % adapter |
| 733 | errMsg += "List of supported adapters: %s" % ', '.join(sorted(list(server_names.keys()))) |
| 734 | else: |
| 735 | errMsg = "Server support for adapter '%s' is not installed on this system " % adapter |
| 736 | errMsg += "(Note: you can try to install it with 'apt install python-%s' or 'pip%s install %s')" % (adapter, '3' if six.PY3 else "", adapter) |
| 737 | logger.critical(errMsg) |
| 738 | |
| 739 | def _client(url, options=None): |
| 740 | logger.debug("Calling '%s'" % url) |
no test coverage detected
searching dependent graphs…