# core/plugs/api.py
#
#
""" Object Copy API. """
__copyright__ = "Copyright 2014 B.H.J Thate"
## IMPORTS
from core.utils import run_thr, error, get_exception, list_files, j, get_source
from core import Object, kernel, __version__, hostname
# imports
import urllib.parse
import urllib
import logging
import select
import socket
import time
import http
import cgi
import sys
import os
from http.server import HTTPServer, BaseHTTPRequestHandler
## DEFINES
port = 10102
server = None
## HANDLERS
handlers = Object()
## APIServer class
[docs]class APIServer(HTTPServer, Object):
""" API server """
allow_reuse_address = True
daemon_thread = True
def __init__(zelf, *args, **kwargs):
""" start the API server. """
HTTPServer.__init__(zelf, *args, **kwargs)
Object.__init__(zelf)
logging.warn("running on http://%s:%s/" % args[0])
zelf.host = args[0]
zelf._status = Object()
zelf._status.status = "init"
zelf._state = Object()
zelf._state.boot = time.time()
zelf._state.start = time.time()
zelf._state.input = time.time()
zelf._state.output = time.time()
zelf.poll = select.poll()
zelf.poll.register(zelf)
[docs] def exit(zelf):
""" shutdown the API server. """
zelf._state.status = "exit"
time.sleep(0.2)
zelf.server_close()
[docs] def start(zelf, *args, **kwargs):
""" serving requests. """
zelf._status.status = "running"
zelf.ready()
while zelf._status.status:
got = zelf.poll.poll(100)
zelf.handle_request()
zelf._state.input = time.time()
[docs] def handle_error(zelf, request, addr):
""" log the error """
ex = get_exception()
logging.warn('%s - %s' % (addr, ex))
## RestReqeustHandler class
[docs]class APIHandler(BaseHTTPRequestHandler):
""" timeserver request handler class """
[docs] def setup(zelf):
""" called on each incoming request. """
BaseHTTPRequestHandler.setup(zelf)
zelf._state = Object()
zelf._state.ip = zelf.client_address[0]
zelf._state.size = 0
[docs] def write_header(zelf, type='text/plain'):
""" write headers to the client. """
zelf.send_response(200)
zelf.send_header('Content-type', '%s; charset=%s ' % (type, "utf-8"))
zelf.send_header('Server', __version__)
zelf.end_headers()
[docs] def handle_request(zelf):
""" handle a REST request. """
zelf.parsed = urllib.parse.urlparse(zelf.path)
path = "/" + zelf.parsed[2].split("/")[1]
try:
for functor in handlers[path]:
result = functor.func(zelf, zelf.request)
except KeyError as ex: logging.info("missing %s" % str(ex))
except: error()
do_DELETE = do_PUT = do_GET = do_POST = handle_request
[docs] def log_request(zelf, code):
""" log the request """
try: ua = zelf.headers['user-agent']
except: ua = "-"
try: rf = zelf.headers['referer']
except: rf = "-"
logging.warn('%s %s %s' % (zelf.address_string(), code, zelf.path))
server = None
[docs]def api_home(handler, request):
server, port = handler.server.host
handler.write_header()
handler.wfile.write(bytes("C O R E L I B !!", "utf-8"))
handler.wfile.write(bytes("\n\nAPI INTERFACE\n\n", "utf-8"))
for func in handlers.keys():
handler.wfile.write(bytes("http://%s:%s%s\n" % (server, port, func), "utf-8"))
handler.wfile.flush()
[docs]def api_all(handler, request):
o = Object()
nr = 0
server, port = handler.server.host
for fn in list_files(kernel.cfg.workdir):
o[nr] = "http://%s:%s/get/%s" % (server, port, fn.split(os.sep)[-1])
nr += 1
handler.write_header()
handler.wfile.write(bytes(o.to_json(indent=2), "utf-8"))
[docs]def api_get(handler, request):
fn = os.sep.join(handler.path.split("/")[2:])
path = os.path.normpath(os.path.expanduser(j(kernel.cfg.workdir, fn)))
o = Object()
o.load(path)
handler.write_header()
handler.wfile.write(bytes(o.to_json(indent=2, ensure_ascii=False, sort_keys=True), "utf-8"))
[docs]def api_show(handler, request):
fn = os.sep.join(handler.path.split("/")[2:])
path = os.path.normpath(os.path.expanduser(j(kernel.cfg.workdir, fn)))
o = Object()
o.load(path)
txt = o.pretty()
txt = txt.replace("\\n", "\n")
txt = txt.replace("\\t", "\t")
handler.write_header()
handler.wfile.write(bytes(txt, "utf-8"))
[docs]def init(*args, **kwargs):
global server
server = APIServer((hostname, port), APIHandler)
handlers.register("/", api_home)
handlers.register("/all", api_all)
handlers.register("/get", api_get)
handlers.register("/show", api_show)
kernel.services.api = server
kernel.workers.put(server.start, ())
[docs]def shutdown(*args, **kwargs): server.close()