⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtk_cherrypy_wsgiserver.py

📁 LINUX下
💻 PY
📖 第 1 页 / 共 3 页
字号:
                conn = self.server.requests.get()                if conn is _SHUTDOWNREQUEST:                    return                try:                    conn.communicate()                finally:                    conn.close()        except (KeyboardInterrupt, SystemExit), exc:            self.server.interrupt = excclass SSLConnection:    """A thread-safe wrapper for an SSL.Connection.    *args: the arguments to create the wrapped SSL.Connection(*args).    """    def __init__(self, *args):        self._ssl_conn = SSL.Connection(*args)        self._lock = threading.RLock()    for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read',              'renegotiate', 'bind', 'listen', 'connect', 'accept',              'setblocking', 'fileno', 'shutdown', 'close', 'get_cipher_list',              'getpeername', 'getsockname', 'getsockopt', 'setsockopt',              'makefile', 'get_app_data', 'set_app_data', 'state_string',              'sock_shutdown', 'get_peer_certificate', 'want_read',              'want_write', 'set_connect_state', 'set_accept_state',              'connect_ex', 'sendall', 'settimeout'):        exec """def %s(self, *args):        self._lock.acquire()        try:            return self._ssl_conn.%s(*args)        finally:            self._lock.release()""" % (f, f)class CherryPyWSGIServer(object):    """An HTTP server for WSGI.    bind_addr: a (host, port) tuple if TCP sockets are desired;        for UNIX sockets, supply the filename as a string.    wsgi_app: the WSGI 'application callable'; multiple WSGI applications        may be passed as (script_name, callable) pairs.    numthreads: the number of worker threads to create (default 10).    server_name: the string to set for WSGI's SERVER_NAME environ entry.        Defaults to socket.gethostname().    max: the maximum number of queued requests (defaults to -1 = no limit).    request_queue_size: the 'backlog' argument to socket.listen();        specifies the maximum number of queued connections (default 5).    timeout: the timeout in seconds for accepted connections (default 10).    protocol: the version string to write in the Status-Line of all        HTTP responses. For example, "HTTP/1.1" (the default). This        also limits the supported features used in the response.    SSL/HTTPS    ---------    The OpenSSL module must be importable for SSL functionality.    You can obtain it from http://pyopenssl.sourceforge.net/    ssl_certificate: the filename of the server SSL certificate.    ssl_privatekey: the filename of the server's private key file.    If either of these is None (both are None by default), this server    will not use SSL. If both are given and are valid, they will be read    on server start and used in the SSL context for the listening socket.    """    protocol = "HTTP/1.1"    version = "CherryPy/3.0.2"    ready = False    _interrupt = None    ConnectionClass = HTTPConnection    # Paths to certificate and private key files    ssl_certificate = None    ssl_private_key = None    def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None,                 max=-1, request_queue_size=5, timeout=10):        self.requests = Queue.Queue(max)        if callable(wsgi_app):            # We've been handed a single wsgi_app, in CP-2.1 style.            # Assume it's mounted at "".            self.mount_points = [("", wsgi_app)]        else:            # We've been handed a list of (mount_point, wsgi_app) tuples,            # so that the server can call different wsgi_apps, and also            # correctly set SCRIPT_NAME.            self.mount_points = wsgi_app        self.mount_points.sort()        self.mount_points.reverse()        self.bind_addr = bind_addr        self.numthreads = numthreads or 1        if not server_name:            server_name = socket.gethostname()        self.server_name = server_name        self.request_queue_size = request_queue_size        self._workerThreads = []        self.gtk_idle_id = None        self.timeout = timeout    def start_common(self):        """Run the server forever."""        # We don't have to trap KeyboardInterrupt or SystemExit here,        # because cherrpy.server already does so, calling self.stop() for us.        # If you're using this server with another framework, you should        # trap those exceptions in whatever code block calls start().        self._interrupt = None        # Select the appropriate socket        if isinstance(self.bind_addr, basestring):            # AF_UNIX socket            # So we can reuse the socket...            try: os.unlink(self.bind_addr)            except: pass            # So everyone can access the socket...            try: os.chmod(self.bind_addr, 0777)            except: pass            info = [(socket.AF_UNIX, socket.SOCK_STREAM, 0, "", self.bind_addr)]        else:            # AF_INET or AF_INET6 socket            # Get the correct address family for our host (allows IPv6 addresses)            host, port = self.bind_addr            flags = 0            if host == '':                # Despite the socket module docs, using '' does not                # allow AI_PASSIVE to work. Passing None instead                # returns '0.0.0.0' like we want. In other words:                #     host    AI_PASSIVE     result                #      ''         Y         192.168.x.y                #      ''         N         192.168.x.y                #     None        Y         0.0.0.0                #     None        N         127.0.0.1                host = None                flags = socket.AI_PASSIVE            try:                info = socket.getaddrinfo(host, port, socket.AF_UNSPEC,                                          socket.SOCK_STREAM, 0, flags)            except socket.gaierror:                # Probably a DNS issue. Assume IPv4.                info = [(socket.AF_INET, socket.SOCK_STREAM, 0, "", self.bind_addr)]        self.socket = None        msg = "No socket could be created"        for res in info:            af, socktype, proto, canonname, sa = res            try:                self.bind(af, socktype, proto)            except socket.error, msg:                if self.socket:                    self.socket.close()                self.socket = None                continue            break        if not self.socket:            raise socket.error, msg        # Timeout so KeyboardInterrupt can be caught on Win32        self.socket.settimeout(1)        self.socket.listen(self.request_queue_size)        # Create worker threads        for i in xrange(self.numthreads):            self._workerThreads.append(WorkerThread(self))        for worker in self._workerThreads:            worker.setName("CP WSGIServer " + worker.getName())            worker.start()        for worker in self._workerThreads:            while not worker.ready:                time.sleep(.1)        self.ready = True    def start(self):        self.start_common()        while self.ready:            self.tick()            if self.interrupt:                while self.interrupt is True:                    # Wait for self.stop() to complete. See _set_interrupt.                    time.sleep(0.1)                raise self.interrupt    def start_gtk(self):        self.start_common()        self.socket.settimeout(0.0001)        self.timeout = 0.3        self.gtk_idle_id = gobject.idle_add(self.tick)        #self.gtk_idle_id = gobject.timeout_add(100, self.tick) #needs tweaking!    def bind(self, family, type, proto=0):        """Create (or recreate) the actual socket object."""        self.socket = socket.socket(family, type, proto)        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)##        self.socket.setsockopt(socket.SOL_SOCKET, socket.TCP_NODELAY, 1)        if self.ssl_certificate and self.ssl_private_key:            if SSL is None:                raise ImportError("You must install pyOpenSSL to use HTTPS.")            # See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473            ctx = SSL.Context(SSL.SSLv23_METHOD)            ctx.use_privatekey_file(self.ssl_private_key)            ctx.use_certificate_file(self.ssl_certificate)            self.socket = SSLConnection(ctx, self.socket)            self.populate_ssl_environ()        self.socket.bind(self.bind_addr)    def tick(self):        """Accept a new connection and put it on the Queue."""        #print 'tick!'        try:            s, addr = self.socket.accept()            if not self.ready:                return True            if hasattr(s, 'settimeout'):                s.settimeout(self.timeout)            conn = self.ConnectionClass(s, addr, self)            self.requests.put(conn)        except socket.timeout:            # The only reason for the timeout in start() is so we can            # notice keyboard interrupts on Win32, which don't interrupt            # accept() by default            # mvoncken and i'ts usefull for gtk too.            return True        except socket.error, x:            msg = x.args[1]            if msg in ("Bad file descriptor", "Socket operation on non-socket"):                # Our socket was closed.                return True            if msg == "Resource temporarily unavailable":                # Just try again. See http://www.cherrypy.org/ticket/479.                return True            raise #mvoncken:should it raise here?        return True    def _get_interrupt(self):        return self._interrupt    def _set_interrupt(self, interrupt):        self._interrupt = True        self.stop()        self._interrupt = interrupt    interrupt = property(_get_interrupt, _set_interrupt,                         doc="Set this to an Exception instance to "                             "interrupt the server.")    def stop(self):        """Gracefully shutdown a server that is serving forever."""        self.ready = False        sock = getattr(self, "socket", None)        if sock:            if not isinstance(self.bind_addr, basestring):                # Touch our own socket to make accept() return immediately.                try:                    host, port = sock.getsockname()[:2]                except socket.error, x:                    if x.args[1] != "Bad file descriptor":                        raise                else:                    # Note that we're explicitly NOT using AI_PASSIVE,                    # here, because we want an actual IP to touch.                    # localhost won't work if we've bound to a public IP,                    # but it would if we bound to INADDR_ANY via host = ''.                    for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC,                                                  socket.SOCK_STREAM):                        af, socktype, proto, canonname, sa = res                        s = None                        try:                            s = socket.socket(af, socktype, proto)                            # See http://groups.google.com/group/cherrypy-users/                            #        browse_frm/thread/bbfe5eb39c904fe0                            s.settimeout(1.0)                            s.connect((host, port))                            s.close()                        except socket.error:                            if s:                                s.close()            if hasattr(sock, "close"):                sock.close()            self.socket = None        # Must shut down threads here so the code that calls        # this method can know when all threads are stopped.        for worker in self._workerThreads:            self.requests.put(_SHUTDOWNREQUEST)        # Don't join currentThread (when stop is called inside a request).        current = threading.currentThread()        while self._workerThreads:            worker = self._workerThreads.pop()            if worker is not current and worker.isAlive:                try:                    worker.join()                except AssertionError:                    pass    def stop_gtk(self):        self.stop()        if self.gtk_idle_id == None:            raise Exception('gtk_idle_id == None in stop_gtk')        gobject.source_remove(self.gtk_idle_id)        self.gtk_idle_id = None    def populate_ssl_environ(self):        """Create WSGI environ entries to be merged into each request."""        cert = open(self.ssl_certificate).read()        cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)        self.ssl_environ = {            # pyOpenSSL doesn't provide access to any of these AFAICT##            'SSL_PROTOCOL': 'SSLv2',##            SSL_CIPHER 	string 	The cipher specification name##            SSL_VERSION_INTERFACE 	string 	The mod_ssl program version##            SSL_VERSION_LIBRARY 	string 	The OpenSSL program version            }        # Server certificate attributes        self.ssl_environ.update({            'SSL_SERVER_M_VERSION': cert.get_version(),            'SSL_SERVER_M_SERIAL': cert.get_serial_number(),##            'SSL_SERVER_V_START': Validity of server's certificate (start time),##            'SSL_SERVER_V_END': Validity of server's certificate (end time),            })        for prefix, dn in [("I", cert.get_issuer()),                           ("S", cert.get_subject())]:            # X509Name objects don't seem to have a way to get the            # complete DN string. Use str() and slice it instead,            # because str(dn) == "<X509Name object '/C=US/ST=...'>"            dnstr = str(dn)[18:-2]            wsgikey = 'SSL_SERVER_%s_DN' % prefix            self.ssl_environ[wsgikey] = dnstr            # The DN should be of the form: /k1=v1/k2=v2, but we must allow            # for any value to contain slashes itself (in a URL).            while dnstr:                pos = dnstr.rfind("=")                dnstr, value = dnstr[:pos], dnstr[pos + 1:]                pos = dnstr.rfind("/")                dnstr, key = dnstr[:pos], dnstr[pos + 1:]                if key and value:                    wsgikey = 'SSL_SERVER_%s_DN_%s' % (prefix, key)                    self.ssl_environ[wsgikey] = value

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -