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

📄 gtk_cherrypy_wsgiserver.py

📁 LINUX下
💻 PY
📖 第 1 页 / 共 3 页
字号:
            environ["CONTENT_LENGTH"] = cl    def decode_chunked(self):        """Decode the 'chunked' transfer coding."""        cl = 0        data = StringIO.StringIO()        while True:            line = self.rfile.readline().strip().split(";", 1)            chunk_size = int(line.pop(0), 16)            if chunk_size <= 0:                break##            if line: chunk_extension = line[0]            cl += chunk_size            data.write(self.rfile.read(chunk_size))            crlf = self.rfile.read(2)            if crlf != "\r\n":                self.simple_response("400 Bad Request",                                     "Bad chunked transfer coding "                                     "(expected '\\r\\n', got %r)" % crlf)                return        # Grab any trailer headers        self.read_headers()        data.seek(0)        self.environ["wsgi.input"] = data        self.environ["CONTENT_LENGTH"] = str(cl) or ""        return True    def respond(self):        """Call the appropriate WSGI app and write its iterable output."""        response = self.wsgi_app(self.environ, self.start_response)        try:            for chunk in response:                # "The start_response callable must not actually transmit                # the response headers. Instead, it must store them for the                # server or gateway to transmit only after the first                # iteration of the application return value that yields                # a NON-EMPTY string, or upon the application's first                # invocation of the write() callable." (PEP 333)                if chunk:                    self.write(chunk)        finally:            if hasattr(response, "close"):                response.close()        if (self.ready and not self.sent_headers                and not self.connection.server.interrupt):            self.sent_headers = True            self.send_headers()        if self.chunked_write:            self.sendall("0\r\n\r\n")    def simple_response(self, status, msg=""):        """Write a simple response back to the client."""        status = str(status)        buf = ["%s %s\r\n" % (self.connection.server.protocol, status),               "Content-Length: %s\r\n" % len(msg)]        if status[:3] == "413" and self.response_protocol == 'HTTP/1.1':            # Request Entity Too Large            self.close_connection = True            buf.append("Connection: close\r\n")        buf.append("\r\n")        if msg:            buf.append(msg)        self.sendall("".join(buf))    def start_response(self, status, headers, exc_info = None):        """WSGI callable to begin the HTTP response."""        if self.started_response:            if not exc_info:                raise AssertionError("WSGI start_response called a second "                                     "time with no exc_info.")            else:                try:                    raise exc_info[0], exc_info[1], exc_info[2]                finally:                    exc_info = None        self.started_response = True        self.status = status        self.outheaders.extend(headers)        return self.write    def write(self, chunk):        """WSGI callable to write unbuffered data to the client.        This method is also used internally by start_response (to write        data from the iterable returned by the WSGI application).        """        if not self.started_response:            raise AssertionError("WSGI write called before start_response.")        if not self.sent_headers:            self.sent_headers = True            self.send_headers()        if self.chunked_write and chunk:            buf = [hex(len(chunk))[2:], "\r\n", chunk, "\r\n"]            self.sendall("".join(buf))        else:            self.sendall(chunk)    def send_headers(self):        """Assert, process, and send the HTTP response message-headers."""        hkeys = [key.lower() for key, value in self.outheaders]        status = int(self.status[:3])        if status == 413:            # Request Entity Too Large. Close conn to avoid garbage.            self.close_connection = True        elif "content-length" not in hkeys:            # "All 1xx (informational), 204 (no content),            # and 304 (not modified) responses MUST NOT            # include a message-body." So no point chunking.            if status < 200 or status in (204, 205, 304):                pass            else:                if self.response_protocol == 'HTTP/1.1':                    # Use the chunked transfer-coding                    self.chunked_write = True                    self.outheaders.append(("Transfer-Encoding", "chunked"))                else:                    # Closing the conn is the only way to determine len.                    self.close_connection = True        if "connection" not in hkeys:            if self.response_protocol == 'HTTP/1.1':                if self.close_connection:                    self.outheaders.append(("Connection", "close"))            else:                if not self.close_connection:                    self.outheaders.append(("Connection", "Keep-Alive"))        if "date" not in hkeys:            self.outheaders.append(("Date", rfc822.formatdate()))        server = self.connection.server        if "server" not in hkeys:            self.outheaders.append(("Server", server.version))        buf = [server.protocol, " ", self.status, "\r\n"]        try:            buf += [k + ": " + v + "\r\n" for k, v in self.outheaders]        except TypeError:            if not isinstance(k, str):                raise TypeError("WSGI response header key %r is not a string.")            if not isinstance(v, str):                raise TypeError("WSGI response header value %r is not a string.")            else:                raise        buf.append("\r\n")        self.sendall("".join(buf))class NoSSLError(Exception):    """Exception raised when a client speaks HTTP to an HTTPS socket."""    passdef _ssl_wrap_method(method, is_reader=False):    """Wrap the given method with SSL error-trapping.    is_reader: if False (the default), EOF errors will be raised.        If True, EOF errors will return "" (to emulate normal sockets).    """    def ssl_method_wrapper(self, *args, **kwargs):##        print (id(self), method, args, kwargs)        start = time.time()        while True:            try:                return method(self, *args, **kwargs)            except (SSL.WantReadError, SSL.WantWriteError):                # Sleep and try again. This is dangerous, because it means                # the rest of the stack has no way of differentiating                # between a "new handshake" error and "client dropped".                # Note this isn't an endless loop: there's a timeout below.                time.sleep(self.ssl_retry)            except SSL.SysCallError, e:                if is_reader and e.args == (-1, 'Unexpected EOF'):                    return ""                errno = e.args[0]                if is_reader and errno in socket_errors_to_ignore:                    return ""                raise socket.error(errno)            except SSL.Error, e:                if is_reader and e.args == (-1, 'Unexpected EOF'):                    return ""                thirdarg = None                try:                    thirdarg = e.args[0][0][2]                except IndexError:                    pass                if is_reader and thirdarg == 'ssl handshake failure':                    return ""                if thirdarg == 'http request':                    # The client is talking HTTP to an HTTPS server.                    raise NoSSLError()                raise            if time.time() - start > self.ssl_timeout:                raise socket.timeout("timed out")    return ssl_method_wrapperclass SSL_fileobject(socket._fileobject):    """Faux file object attached to a socket object."""    ssl_timeout = 3    ssl_retry = .01    close = _ssl_wrap_method(socket._fileobject.close)    flush = _ssl_wrap_method(socket._fileobject.flush)    write = _ssl_wrap_method(socket._fileobject.write)    writelines = _ssl_wrap_method(socket._fileobject.writelines)    read = _ssl_wrap_method(socket._fileobject.read, is_reader=True)    readline = _ssl_wrap_method(socket._fileobject.readline, is_reader=True)    readlines = _ssl_wrap_method(socket._fileobject.readlines, is_reader=True)class HTTPConnection(object):    """An HTTP connection (active socket).    socket: the raw socket object (usually TCP) for this connection.    addr: the "bind address" for the remote end of the socket.        For IP sockets, this is a tuple of (REMOTE_ADDR, REMOTE_PORT).        For UNIX domain sockets, this will be a string.    server: the HTTP Server for this Connection. Usually, the server        object possesses a passive (server) socket which spawns multiple,        active (client) sockets, one for each connection.    environ: a WSGI environ template. This will be copied for each request.    rfile: a fileobject for reading from the socket.    sendall: a function for writing (+ flush) to the socket.    """    rbufsize = -1    RequestHandlerClass = HTTPRequest    environ = {"wsgi.version": (1, 0),               "wsgi.url_scheme": "http",               "wsgi.multithread": True,               "wsgi.multiprocess": False,               "wsgi.run_once": False,               "wsgi.errors": sys.stderr,               }    def __init__(self, sock, addr, server):        self.socket = sock        self.addr = addr        self.server = server        # Copy the class environ into self.        self.environ = self.environ.copy()        if SSL and isinstance(sock, SSL.ConnectionType):            timeout = sock.gettimeout()            self.rfile = SSL_fileobject(sock, "r", self.rbufsize)            self.rfile.ssl_timeout = timeout            self.sendall = _ssl_wrap_method(sock.sendall)            self.environ["wsgi.url_scheme"] = "https"            self.environ["HTTPS"] = "on"            sslenv = getattr(server, "ssl_environ", None)            if sslenv:                self.environ.update(sslenv)        else:            self.rfile = sock.makefile("rb", self.rbufsize)            self.sendall = sock.sendall        self.environ.update({"wsgi.input": self.rfile,                             "SERVER_NAME": self.server.server_name,                             })        if isinstance(self.server.bind_addr, basestring):            # AF_UNIX. This isn't really allowed by WSGI, which doesn't            # address unix domain sockets. But it's better than nothing.            self.environ["SERVER_PORT"] = ""        else:            self.environ["SERVER_PORT"] = str(self.server.bind_addr[1])            # optional values            # Until we do DNS lookups, omit REMOTE_HOST            self.environ["REMOTE_ADDR"] = self.addr[0]            self.environ["REMOTE_PORT"] = str(self.addr[1])    def communicate(self):        """Read each request and respond appropriately."""        try:            while True:                # (re)set req to None so that if something goes wrong in                # the RequestHandlerClass constructor, the error doesn't                # get written to the previous request.                req = None                req = self.RequestHandlerClass(self)                # This order of operations should guarantee correct pipelining.                req.parse_request()                if not req.ready:                    return                req.respond()                if req.close_connection:                    return        except socket.error, e:            errno = e.args[0]            if errno not in socket_errors_to_ignore:                if req:                    req.simple_response("500 Internal Server Error",                                        format_exc())            return        except (KeyboardInterrupt, SystemExit):            raise        except NoSSLError:            # Unwrap our sendall            req.sendall = self.socket._sock.sendall            req.simple_response("400 Bad Request",                                "The client sent a plain HTTP request, but "                                "this server only speaks HTTPS on this port.")        except:            if req:                req.simple_response("500 Internal Server Error", format_exc())    def close(self):        """Close the socket underlying this connection."""        self.rfile.close()        self.socket.close()def format_exc(limit=None):    """Like print_exc() but return a string. Backport for Python 2.3."""    try:        etype, value, tb = sys.exc_info()        return ''.join(traceback.format_exception(etype, value, tb, limit))    finally:        etype = value = tb = None_SHUTDOWNREQUEST = Noneclass WorkerThread(threading.Thread):    """Thread which continuously polls a Queue for Connection objects.    server: the HTTP Server which spawned this thread, and which owns the        Queue and is placing active connections into it.    ready: a simple flag for the calling server to know when this thread        has begun polling the Queue.    Due to the timing issues of polling a Queue, a WorkerThread does not    check its own 'ready' flag after it has started. To stop the thread,    it is necessary to stick a _SHUTDOWNREQUEST object onto the Queue    (one for each running WorkerThread).    """    def __init__(self, server):        self.ready = False        self.server = server        threading.Thread.__init__(self)    def run(self):        try:            self.ready = True            while True:

⌨️ 快捷键说明

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