gozerbot.rest.server

a simple REST server.

class gozerbot.rest.server.RestRequestHandler(request, client_address, server)

Bases: BaseHTTPServer.BaseHTTPRequestHandler

timeserver request handler class

do_DELETE()

handle the request.

do_GET()

handle the request.

do_POST()

handle the request.

do_PUT()

handle the request.

handle_request()

handle the request.

log_request(code)

log the request

sendresult()

send result to the stream.

setup()

setup the connection.

writeheader(type='text/plain')

write the header to the stream.

class gozerbot.rest.server.RestServer(server_address, RequestHandlerClass, bind_and_activate=True)

Bases: SocketServer.ThreadingMixIn, gozerbot.rest.server.RestServerBase

class gozerbot.rest.server.RestServerAsync(server_address, RequestHandlerClass, bind_and_activate=True)

Bases: gozerbot.rest.server.RestServerBase, asyncore.dispatcher

class gozerbot.rest.server.RestServerBase(server_address, RequestHandlerClass, bind_and_activate=True)

Bases: BaseHTTPServer.HTTPServer

REST web server

addhandler(path, type, handler)

add a web handler

blacklist()

show blacklist.

disable(what)

disable an entry point.

do(request)

do a request

enable(what)

enable an entry point.

entrypoint(request)

check for white and blacklists before processing the request any further.

handle_error(request, addr)

log the error

serve()

REST server loop.

shutdown()

shutdown the REST server.

start()
whitelist()

show the whitelist.

whitelistenable()

show whitelistenable.

class gozerbot.rest.server.SecureAuthRestServer(server_address, HandlerClass, chain, serverkey, servercert)

Bases: gozerbot.rest.server.SecureRestServer

implement a secure REST server that uses auth (not working yet).

class gozerbot.rest.server.SecureRequestHandler(request, client_address, server)

Bases: gozerbot.rest.server.RestRequestHandler

secure request handler.

setup()
class gozerbot.rest.server.SecureRestServer(server_address, HandlerClass, keyfile, certfile)

Bases: gozerbot.rest.server.RestServer

implement a secure rest server (not wkrking yet.

CODE

# gozerbot/rest/server.py
#
#

""" a simple REST server. """

__status__ = "seen"

gozerbot imports

from gozerbot.utils.log import rlog
from gozerbot.utils.exception import handle_exception, exceptionmsg
from gozerbot.utils.trace import calledfrom
from gozerbot.config import config
from gozerbot.persist.persiststate import ObjectState
from gozerbot.threads.thr import start_new_thread

basic imports

from SocketServer import BaseServer, ThreadingMixIn
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from urllib import unquote_plus
from asyncore import dispatcher
from cgi import escape
import time
import sys
import select
import types
import socket

RestServerBase class

class RestServerBase(HTTPServer):

    """ REST web server """

    allow_reuse_address = True
    daemon_thread = True

    def start(self):
        self.name = calledfrom(sys._getframe(0))
        self.stop = False
        self.running = False
        self.handlers = {}
        self.webmods = {}
        self.state = ObjectState()
        self.state.define('whitelistenable', 0)
        self.state.define('whitelist', [])
        self.state.define('blacklist', [])
        self.state.define('disable', [])
        self.poll = select.poll()
        self.poll.register(self)
        start_new_thread(self.serve, ())

    def shutdown(self):
        """ shutdown the REST server. """
        try:
            self.stop = True
            time.sleep(0.2)
            self.server_close()
        except Exception, ex: handle_exception()

    def serve(self):
        """ REST server loop. """
        rlog(10, self.name, 'starting server')
        time.sleep(1)
        while not self.stop:
            self.running = True
            try: got = self.poll.poll(100)
            except Exception, ex: handle_exception()
            if got and not self.stop:
                try: self.handle_request()
                except Exception, ex: handle_exception()
            time.sleep(0.01)
        self.running = False
        rlog(10, self.name, 'stopping server')

    def entrypoint(self, request):
        """ check for white and blacklists before processing the request any further. """
        ip = request.ip
        if not self.whitelistenable() and ip in self.blacklist():
            rlog(100, self.name, 'denied %s' % ip)
            request.send_error(401)
            return False
        if  self.whitelistenable() and ip not in self.whitelist():
            rlog(100, self.name, 'denied %s' % ip)
            request.send_error(401)
            return False
        return True

    def whitelistenable(self):
        """ show whitelistenable. """
        return self.state['whitelistenable']

    def whitelist(self):
        """ show the whitelist. """
        return self.state['whitelist']

    def blacklist(self):
        """ show blacklist. """
        return self.state['blacklist']

    def addhandler(self, path, type, handler):
        """ add a web handler """
        splitted = []
        for i in path.split('/'):
            if i: splitted.append(i)
        splitted = tuple(splitted)
        if not self.handlers.has_key(splitted): self.handlers[splitted] = {}
        self.handlers[splitted][type] = handler
        rlog(0, self.name, '%s %s handler added' % (splitted, type))

    def enable(self, what):
        """ enable an entry point. """
        try:
            self.state['disable'].remove(what)
            rlog(10, self.name, 'enabled %s' % str(what))
        except ValueError: pass

    def disable(self, what):
        """ disable an entry point. """
        self.state['disable'].append(what)
        rlog(10, self.name, 'enabled %s' % str(what))

    def do(self, request):
        """ do a request """
        path = request.path.split('?')[0]
        if path.endswith('/'): path = path[:-1]
        splitted = []
        for i in path.split('/'):
            if i: splitted.append(i)
        splitted = tuple(splitted)
        for i in self.state['disable']:
            if i in splitted:
                rlog(10, self.name, 'denied disabled %s' % i)
                request.send_error(404)
                return
        request.splitted = splitted
        request.value = None
        type = request.command
        try: func = self.handlers[splitted][type]
        except (KeyError, ValueError):
            try:
                func = self.handlers[splitted[:-1]][type]
                request.value = splitted[-1]
            except (KeyError, ValueError): request.send_error(404) ; return
        result = func(self, request)
        rlog(10, self.name, 'result: %s' % str(result))
        return result

    def handle_error(self, request, addr):
        """ log the error """
        exctype, excvalue, tb = sys.exc_info()
        if exctype == socket.timeout:
            rlog(10, self.name, 'socket timeout on %s' % str(addr))
            return
        if exctype == socket.error:
            rlog(10, self.name, 'socket error on %s: %s' % (str(addr), excvalue))
            return
        exceptstr = exceptionmsg()
        rlog(10, self.name, 'error on %s: %s %s => %s' % (str(addr), exctype, excvalue, exceptstr))

RestServer class

class RestServer(ThreadingMixIn, RestServerBase):

    pass

RestServerAsybc class

class RestServerAsync(RestServerBase, dispatcher):

    pass

RestRequestHandler class

class RestRequestHandler(BaseHTTPRequestHandler):

    """ timeserver request handler class """

    def setup(self):
        """ setup the connection. """
        BaseHTTPRequestHandler.setup(self)
        self.ip = self.client_address[0]
        self.name = self.ip
        self.size = 0

    def writeheader(self, type='text/plain'):
        """ write the header to the stream. """
        self.send_response(200)
        self.send_header('Content-type', '%s; charset=%s ' % (type,sys.getdefaultencoding()))
        self.send_header('Server', config['version'])
        self.end_headers()

    def sendresult(self):
        """ send result to the stream. """
        try:
            result = self.server.do(self)
            if not result: return
            self.size = len(result)
        except Exception, ex:
            handle_exception()
            self.send_error(501)
            return
        self.writeheader()
        self.wfile.write(result)
        self.wfile.close()

    def handle_request(self):
        """ handle the request. """
        if not self.server.entrypoint(self): return
        self.sendresult()

    do_DELETE = do_PUT = do_GET = do_POST = handle_request

    def log_request(self, code):
        """ log the request """
        try: ua = self.headers['user-agent']
        except: ua = "-"
        try: rf = self.headers['referer']
        except: rf = "-"
        if hasattr(self, 'path'):
            rlog(10, self.name, '%s "%s %s %s" %s %s "%s" "%s"' % (self.address_string(), self.command, self.path, self.request_version, code, self.size, rf, ua))
        else:
            rlog(10, self.name, '%s "%s %s %s" %s %s "%s" "%s"' % (self.address_string(), self.command, "none", self.request_version, code, self.size, rf, ua))

SecureRestServer class

class SecureRestServer(RestServer):

    """ implement a secure rest server (not wkrking yet. """

    def __init__(self, server_address, HandlerClass, keyfile, certfile):
        from OpenSSL import SSL
        BaseServer.__init__(self, server_address, HandlerClass)
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        ctx.set_options(SSL.OP_NO_SSLv2)
        rlog(10, self.name, "loading private key from %s" % keyfile)
        ctx.use_privatekey_file (keyfile)
        rlog(10, self.name, 'loading certificate from %s' % certfile)
        ctx.use_certificate_file(certfile)
        rlog(10, self.name, 'creating SSL socket on %s' % str(server_address))
        self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type))
        self.server_bind()
        self.server_activate()

SecureAuthRestServer class

class SecureAuthRestServer(SecureRestServer):

    """ implement a secure REST server that uses auth (not working yet). """

    def __init__(self, server_address, HandlerClass, chain, serverkey, servercert):
        from OpenSSL import SSL
        BaseServer.__init__(self, server_address, HandlerClass)
        ctx = SSL.Context(SSL.SSLv23_METHOD)
        rlog(10, self.name, "loading private key from %s" % serverkey)
        ctx.use_privatekey_file (serverkey)
        rlog(10, self.name, 'loading certificate from %s' % servercert)
        ctx.use_certificate_file(servercert)
        rlog(10, self.name, 'loading chain of certifications from %s' % chain)
        ctx.set_verify_depth(2)
        ctx.load_client_ca(chain)
        #ctx.load_verify_locations(chain)
        rlog(10, self.name, 'creating SSL socket on %s' % str(server_address))
        callback = lambda conn,cert,errno,depth,retcode: retcode
        ctx.set_verify(SSL.VERIFY_FAIL_IF_NO_PEER_CERT | SSL.VERIFY_PEER, callback)
        ctx.set_session_id('gozerbot')
        self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
                                                        self.socket_type))
        self.server_bind()
        self.server_activate()

SecureRequestHandler class

class SecureRequestHandler(RestRequestHandler):

    """ secure request handler. """

    def setup(self):
        self.connection = self.request._sock
        self.request._sock.setblocking(1)
        self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
        self.wfile = socket._fileobject(self.request, "wb", self.rbufsize)