Пример #1
0
 def serve(cls, endpoint, handler):
     if isinstance(endpoint, Server):
         assert False, "TODO"
     else:
         #default is to server using SocketServer, endpoint is addresss
         from concurrence.io.socket import SocketServer
         socket_server = SocketServer(endpoint, handler)
         socket_server.serve()
         return socket_server
Пример #2
0
 def serve(cls, endpoint, handler):
     if isinstance(endpoint, Server):
         assert False, "TODO"
     else:
         #default is to server using SocketServer, endpoint is addresss  
         from concurrence.io.socket import SocketServer
         socket_server = SocketServer(endpoint, handler)
         socket_server.serve()
         return socket_server
Пример #3
0
 def serve_socket(self, addr, socket):
     "Runs a WebService instance accepting connections from given socket"
     try:
         from concurrence.io.socket import SocketServer
         self.socket_server = SocketServer(socket,
                                           self.server.handle_connection)
         self.socket_server.serve()
         self.info("serving %s:%d on shared socket", addr[0], addr[1])
         self.addr = (addr[0], addr[1])
     except Exception as err:
         self.exception("Listen %s:%d: %s", addr[0], addr[1], err)
         os._exit(1)
Пример #4
0
 def serve_socket(self, addr, socket):
     "Runs a WebService instance accepting connections from given socket"
     try:
         from concurrence.io.socket import SocketServer
         self.socket_server = SocketServer(socket, self.server.handle_connection)
         self.socket_server.serve()
         self.info("serving %s:%d on shared socket", addr[0], addr[1])
         self.addr = (addr[0], addr[1])
     except Exception as err:
         self.exception("Listen %s:%d: %s", addr[0], addr[1], err)
         os._exit(1)
Пример #5
0
class WebService(Loggable):
    "Abstract web service serving HTTP requests"

    def __init__(self, inst, service_id, service_type, fqn="mg.core.web.WebService"):
        Loggable.__init__(self, fqn)
        self.server = WSGIServer(self.request)
        self.socket_server = None
        self.inst = inst
        self.addr = None
        self.id = service_id
        self.type = service_type
        self.svcinfo = {}
        self.reqs = 0
        self.old_reqstat = self.get_reqstat()

    def get_reqstat(self):
        now = time.time()
        return (now, self.reqs)

    def serve_socket(self, addr, socket):
        "Runs a WebService instance accepting connections from given socket"
        try:
            from concurrence.io.socket import SocketServer
            self.socket_server = SocketServer(socket, self.server.handle_connection)
            self.socket_server.serve()
            self.info("serving %s:%d on shared socket", addr[0], addr[1])
            self.addr = (addr[0], addr[1])
        except Exception as err:
            self.exception("Listen %s:%d: %s", addr[0], addr[1], err)
            os._exit(1)

    def stop(self):
        if self.socket_server:
            self.socket_server.close()
            self.socket_server = None

    def serve(self, addr):
        "Runs a WebService instance listening given port"
        try:
            self.socket_server = self.server.serve(addr)
            self.info("serving %s:%d", addr[0], addr[1])
            self.addr = (addr[0], addr[1])
        except Exception as err:
            self.exception("Listen %s:%d: %s", addr[0], addr[1], err)
            os._exit(1)

    def serve_any_port(self, hostaddr=None, port_min=4000, port_max=4999):
        "Runs a WebService instance listening arbitrarily selected port"
        if hostaddr is None:
            hostaddr = self.inst.instaddr
        for port in xrange(port_min, port_max + 1):
            try:
                try:
                    self.socket_server = self.server.serve((hostaddr, port))
                    self.info("serving %s:%d", hostaddr, port)
                    self.addr = (hostaddr, port)
                    return port
                except socket.error as err:
                    if err.errno == 98:
                        pass
                    else:
                        raise
            except Exception as err:
                self.exception("Listen %s:%d: %s (%s)", hostaddr, port, err, type(err))
                os._exit(1)
        self.error("Couldn't find any available port")
        os._exit(1)

    def req(self):
        try:
            return Tasklet.current().req
        except AttributeError:
            raise RuntimeError("Module.req() called outside of a web handler")

    def request(self, environ, start_response):
        "Process single HTTP request"
        request = Request(environ, start_response)
        Tasklet.current().req = request
        try:
            # remove doubling, leading and trailing slashes, unquote and convert to utf-8
            try:
                uri = re.sub(r'^/*(.*?)/*$', r'\1', re.sub(r'/{2+}', '/', mg.core.tools.urldecode(request.uri())))
            except UnicodeDecodeError:
                return request.send_response("404 Not Found", request.headers, "<html><body><h1>404 Not Found</h1></body></html>")
            else:
                return self.request_uri(request, uri)
        except RuntimeError as e:
            self.error(e)
            e = u"%s" % e
            try:
                if getattr(request, "upload_handler", None):
                    return request.uresponse(htmlescape(json.dumps({"success": False, "errormsg": e})))
            except Exception as e2:
                self.exception(e2)
            if type(e) == unicode:
                e = e.encode("utf-8")
            return request.send_response("500 Internal Server Error", request.headers, "<html><body><h1>500 Internal Server Error</h1>%s</body></html>" % htmlescape(e))
        except Exception as e:
            try:
                self.exception(e)
            except Exception as e2:
                print "Unhandled exception during logging: %s" % e2
                print traceback.format_exc()
            try:
                if getattr(request, "upload_handler", None):
                    return request.uresponse(htmlescape(json.dumps({"success": False, "errormsg": "Internal Server Error"})))
            except Exception as e2:
                self.exception(e2)
            return request.internal_server_error()

    def request_uri(self, request, uri):
        "Process HTTP request after URI was extracted, normalized and converted to utf-8"
        self.reqs += 1
        # /service/call/<svcid>/method
        m = re_service_call.match(uri)
        if m:
            (svcid, remainder) = m.group(1, 2)
            if svcid != self.id:
                return request.bad_request()
            uri = remainder
        # /
        if uri == "":
            res = self.req_handler(request, "index", "index", "")
            if res is not None:
                return res
        # /group/hook[/args]
        m = re_group_hook_args.match(uri)
        if m:
            (group, hook, args) = m.group(1, 2, 3)
            if args is None:
                args = ""
            res = self.req_handler(request, group, hook, args)
            if res is not None:
                return res
        # /group/<SOMETHING_UNHANDLED>
        m = re_group_something_unparsed.match(uri)
        if m:
            (group, args) = m.group(1, 2)
            res = self.req_handler(request, group, "handler", args)
            if res is not None:
                return res
        # /group
        m = re_group.match(uri)
        if m:
            res = self.req_handler(request, uri, "index", "")
            if res is not None:
                return res
        return request.not_found()

    def publish(self, svcinfo):
        "Service may fill svcinfo dict with any additional properties that will be announced in service record"
        old_reqstat = self.old_reqstat
        new_reqstat = self.get_reqstat()
        elapsed = new_reqstat[0] - old_reqstat[0]
        if elapsed > 3:
            svcinfo["svc-rps"] = (new_reqstat[1] - old_reqstat[1]) / elapsed
            self.old_reqstat = new_reqstat

    def set(self, key, val):
        self.svcinfo[key] = val

    def svc_req_handler(self, request, hook):
        return None
Пример #6
0
class WebService(Loggable):
    "Abstract web service serving HTTP requests"

    def __init__(self,
                 inst,
                 service_id,
                 service_type,
                 fqn="mg.core.web.WebService"):
        Loggable.__init__(self, fqn)
        self.server = WSGIServer(self.request)
        self.socket_server = None
        self.inst = inst
        self.addr = None
        self.id = service_id
        self.type = service_type
        self.svcinfo = {}
        self.reqs = 0
        self.old_reqstat = self.get_reqstat()

    def get_reqstat(self):
        now = time.time()
        return (now, self.reqs)

    def serve_socket(self, addr, socket):
        "Runs a WebService instance accepting connections from given socket"
        try:
            from concurrence.io.socket import SocketServer
            self.socket_server = SocketServer(socket,
                                              self.server.handle_connection)
            self.socket_server.serve()
            self.info("serving %s:%d on shared socket", addr[0], addr[1])
            self.addr = (addr[0], addr[1])
        except Exception as err:
            self.exception("Listen %s:%d: %s", addr[0], addr[1], err)
            os._exit(1)

    def stop(self):
        if self.socket_server:
            self.socket_server.close()
            self.socket_server = None

    def serve(self, addr):
        "Runs a WebService instance listening given port"
        try:
            self.socket_server = self.server.serve(addr)
            self.info("serving %s:%d", addr[0], addr[1])
            self.addr = (addr[0], addr[1])
        except Exception as err:
            self.exception("Listen %s:%d: %s", addr[0], addr[1], err)
            os._exit(1)

    def serve_any_port(self, hostaddr=None, port_min=4000, port_max=4999):
        "Runs a WebService instance listening arbitrarily selected port"
        if hostaddr is None:
            hostaddr = self.inst.instaddr
        for port in xrange(port_min, port_max + 1):
            try:
                try:
                    self.socket_server = self.server.serve((hostaddr, port))
                    self.info("serving %s:%d", hostaddr, port)
                    self.addr = (hostaddr, port)
                    return port
                except socket.error as err:
                    if err.errno == 98:
                        pass
                    else:
                        raise
            except Exception as err:
                self.exception("Listen %s:%d: %s (%s)", hostaddr, port, err,
                               type(err))
                os._exit(1)
        self.error("Couldn't find any available port")
        os._exit(1)

    def req(self):
        try:
            return Tasklet.current().req
        except AttributeError:
            raise RuntimeError("Module.req() called outside of a web handler")

    def request(self, environ, start_response):
        "Process single HTTP request"
        request = Request(environ, start_response)
        Tasklet.current().req = request
        try:
            # remove doubling, leading and trailing slashes, unquote and convert to utf-8
            try:
                uri = re.sub(
                    r'^/*(.*?)/*$', r'\1',
                    re.sub(r'/{2+}', '/',
                           mg.core.tools.urldecode(request.uri())))
            except UnicodeDecodeError:
                return request.send_response(
                    "404 Not Found", request.headers,
                    "<html><body><h1>404 Not Found</h1></body></html>")
            else:
                return self.request_uri(request, uri)
        except RuntimeError as e:
            self.error(e)
            e = u"%s" % e
            try:
                if getattr(request, "upload_handler", None):
                    return request.uresponse(
                        htmlescape(
                            json.dumps({
                                "success": False,
                                "errormsg": e
                            })))
            except Exception as e2:
                self.exception(e2)
            if type(e) == unicode:
                e = e.encode("utf-8")
            return request.send_response(
                "500 Internal Server Error", request.headers,
                "<html><body><h1>500 Internal Server Error</h1>%s</body></html>"
                % htmlescape(e))
        except Exception as e:
            try:
                self.exception(e)
            except Exception as e2:
                print "Unhandled exception during logging: %s" % e2
                print traceback.format_exc()
            try:
                if getattr(request, "upload_handler", None):
                    return request.uresponse(
                        htmlescape(
                            json.dumps({
                                "success": False,
                                "errormsg": "Internal Server Error"
                            })))
            except Exception as e2:
                self.exception(e2)
            return request.internal_server_error()

    def request_uri(self, request, uri):
        "Process HTTP request after URI was extracted, normalized and converted to utf-8"
        self.reqs += 1
        # /service/call/<svcid>/method
        m = re_service_call.match(uri)
        if m:
            (svcid, remainder) = m.group(1, 2)
            if svcid != self.id:
                return request.bad_request()
            uri = remainder
        # /
        if uri == "":
            res = self.req_handler(request, "index", "index", "")
            if res is not None:
                return res
        # /group/hook[/args]
        m = re_group_hook_args.match(uri)
        if m:
            (group, hook, args) = m.group(1, 2, 3)
            if args is None:
                args = ""
            res = self.req_handler(request, group, hook, args)
            if res is not None:
                return res
        # /group/<SOMETHING_UNHANDLED>
        m = re_group_something_unparsed.match(uri)
        if m:
            (group, args) = m.group(1, 2)
            res = self.req_handler(request, group, "handler", args)
            if res is not None:
                return res
        # /group
        m = re_group.match(uri)
        if m:
            res = self.req_handler(request, uri, "index", "")
            if res is not None:
                return res
        return request.not_found()

    def publish(self, svcinfo):
        "Service may fill svcinfo dict with any additional properties that will be announced in service record"
        old_reqstat = self.old_reqstat
        new_reqstat = self.get_reqstat()
        elapsed = new_reqstat[0] - old_reqstat[0]
        if elapsed > 3:
            svcinfo["svc-rps"] = (new_reqstat[1] - old_reqstat[1]) / elapsed
            self.old_reqstat = new_reqstat

    def set(self, key, val):
        self.svcinfo[key] = val

    def svc_req_handler(self, request, hook):
        return None