httplib.py

来自「mallet是自然语言处理、机器学习领域的一个开源项目。」· Python 代码 · 共 1,235 行 · 第 1/3 页

PY
1,235
字号
        SharedSocketClient.__init__(self, sock)        self._ssl = ssl        self._buf = ''        self._bufsize = bufsize or self.__class__.BUFSIZE    def _read(self):        buf = ''        # put in a loop so that we retry on transient errors        while 1:            try:                buf = self._ssl.read(self._bufsize)            except socket.sslerror, err:                if (err[0] == socket.SSL_ERROR_WANT_READ                    or err[0] == socket.SSL_ERROR_WANT_WRITE):                    continue                if (err[0] == socket.SSL_ERROR_ZERO_RETURN                    or err[0] == socket.SSL_ERROR_EOF):                    break                raise            except socket.error, err:                if err[0] == errno.EINTR:                    continue                if err[0] == errno.EBADF:                    # XXX socket was closed?                    break                raise            else:                break        return buf    def read(self, size=None):        L = [self._buf]        avail = len(self._buf)        while size is None or avail < size:            s = self._read()            if s == '':                break            L.append(s)            avail += len(s)        all = "".join(L)        if size is None:            self._buf = ''            return all        else:            self._buf = all[size:]            return all[:size]    def readline(self):        L = [self._buf]        self._buf = ''        while 1:            i = L[-1].find("\n")            if i >= 0:                break            s = self._read()            if s == '':                break            L.append(s)        if i == -1:            # loop exited because there is no more data            return "".join(L)        else:            all = "".join(L)            # XXX could do enough bookkeeping not to do a 2nd search            i = all.find("\n") + 1            line = all[:i]            self._buf = all[i:]            return lineclass FakeSocket(SharedSocketClient):    class _closedsocket:        def __getattr__(self, name):            raise error(9, 'Bad file descriptor')    def __init__(self, sock, ssl):        sock = SharedSocket(sock)        SharedSocketClient.__init__(self, sock)        self._ssl = ssl    def close(self):        SharedSocketClient.close(self)        self._sock = self.__class__._closedsocket()    def makefile(self, mode, bufsize=None):        if mode != 'r' and mode != 'rb':            raise UnimplementedFileMode()        return SSLFile(self._shared, self._ssl, bufsize)    def send(self, stuff, flags = 0):        return self._ssl.write(stuff)    sendall = send    def recv(self, len = 1024, flags = 0):        return self._ssl.read(len)    def __getattr__(self, attr):        return getattr(self._sock, attr)class HTTPSConnection(HTTPConnection):    "This class allows communication via SSL."    default_port = HTTPS_PORT    def __init__(self, host, port=None, key_file=None, cert_file=None,                 strict=None):        HTTPConnection.__init__(self, host, port, strict)        self.key_file = key_file        self.cert_file = cert_file    def connect(self):        "Connect to a host on a given (SSL) port."        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        sock.connect((self.host, self.port))        realsock = sock        if hasattr(sock, "_sock"):            realsock = sock._sock        ssl = socket.ssl(realsock, self.key_file, self.cert_file)        self.sock = FakeSocket(sock, ssl)class HTTP:    "Compatibility class with httplib.py from 1.5."    _http_vsn = 10    _http_vsn_str = 'HTTP/1.0'    debuglevel = 0    _connection_class = HTTPConnection    def __init__(self, host='', port=None, strict=None):        "Provide a default host, since the superclass requires one."        # some joker passed 0 explicitly, meaning default port        if port == 0:            port = None        # Note that we may pass an empty string as the host; this will throw        # an error when we attempt to connect. Presumably, the client code        # will call connect before then, with a proper host.        self._setup(self._connection_class(host, port, strict))    def _setup(self, conn):        self._conn = conn        # set up delegation to flesh out interface        self.send = conn.send        self.putrequest = conn.putrequest        self.endheaders = conn.endheaders        self.set_debuglevel = conn.set_debuglevel        conn._http_vsn = self._http_vsn        conn._http_vsn_str = self._http_vsn_str        self.file = None    def connect(self, host=None, port=None):        "Accept arguments to set the host/port, since the superclass doesn't."        if host is not None:            self._conn._set_hostport(host, port)        self._conn.connect()    def getfile(self):        "Provide a getfile, since the superclass' does not use this concept."        return self.file    def putheader(self, header, *values):        "The superclass allows only one value argument."        self._conn.putheader(header, '\r\n\t'.join(values))    def getreply(self):        """Compat definition since superclass does not define it.        Returns a tuple consisting of:        - server status code (e.g. '200' if all goes well)        - server "reason" corresponding to status code        - any RFC822 headers in the response from the server        """        try:            response = self._conn.getresponse()        except BadStatusLine, e:            ### hmm. if getresponse() ever closes the socket on a bad request,            ### then we are going to have problems with self.sock            ### should we keep this behavior? do people use it?            # keep the socket open (as a file), and return it            self.file = self._conn.sock.makefile('rb', 0)            # close our socket -- we want to restart after any protocol error            self.close()            self.headers = None            return -1, e.line, None        self.headers = response.msg        self.file = response.fp        return response.status, response.reason, response.msg    def close(self):        self._conn.close()        # note that self.file == response.fp, which gets closed by the        # superclass. just clear the object ref here.        ### hmm. messy. if status==-1, then self.file is owned by us.        ### well... we aren't explicitly closing, but losing this ref will        ### do it        self.file = Noneif hasattr(socket, 'ssl'):    class HTTPS(HTTP):        """Compatibility with 1.5 httplib interface        Python 1.5.2 did not have an HTTPS class, but it defined an        interface for sending http requests that is also useful for        https.        """        _connection_class = HTTPSConnection        def __init__(self, host='', port=None, key_file=None, cert_file=None,                     strict=None):            # provide a default host, pass the X509 cert info            # urf. compensate for bad input.            if port == 0:                port = None            self._setup(self._connection_class(host, port, key_file,                                               cert_file, strict))            # we never actually use these for anything, but we keep them            # here for compatibility with post-1.5.2 CVS.            self.key_file = key_file            self.cert_file = cert_fileclass HTTPException(Exception):    # Subclasses that define an __init__ must call Exception.__init__    # or define self.args.  Otherwise, str() will fail.    passclass NotConnected(HTTPException):    passclass InvalidURL(HTTPException):    passclass UnknownProtocol(HTTPException):    def __init__(self, version):        self.args = version,        self.version = versionclass UnknownTransferEncoding(HTTPException):    passclass UnimplementedFileMode(HTTPException):    passclass IncompleteRead(HTTPException):    def __init__(self, partial):        self.args = partial,        self.partial = partialclass ImproperConnectionState(HTTPException):    passclass CannotSendRequest(ImproperConnectionState):    passclass CannotSendHeader(ImproperConnectionState):    passclass ResponseNotReady(ImproperConnectionState):    passclass BadStatusLine(HTTPException):    def __init__(self, line):        self.args = line,        self.line = line# for backwards compatibilityerror = HTTPExceptionclass LineAndFileWrapper:    """A limited file-like object for HTTP/0.9 responses."""    # The status-line parsing code calls readline(), which normally    # get the HTTP status line.  For a 0.9 response, however, this is    # actually the first line of the body!  Clients need to get a    # readable file object that contains that line.    def __init__(self, line, file):        self._line = line        self._file = file        self._line_consumed = 0        self._line_offset = 0        self._line_left = len(line)    def __getattr__(self, attr):        return getattr(self._file, attr)    def _done(self):        # called when the last byte is read from the line.  After the        # call, all read methods are delegated to the underlying file        # obhect.        self._line_consumed = 1        self.read = self._file.read        self.readline = self._file.readline        self.readlines = self._file.readlines    def read(self, amt=None):        assert not self._line_consumed and self._line_left        if amt is None or amt > self._line_left:            s = self._line[self._line_offset:]            self._done()            if amt is None:                return s + self._file.read()            else:                return s + self._file.read(amt - len(s))        else:            assert amt <= self._line_left            i = self._line_offset            j = i + amt            s = self._line[i:j]            self._line_offset = j            self._line_left -= amt            if self._line_left == 0:                self._done()            return s    def readline(self):        s = self._line[self._line_offset:]        self._done()        return s    def readlines(self, size=None):        L = [self._line[self._line_offset:]]        self._done()        if size is None:            return L + self._file.readlines()        else:            return L + self._file.readlines(size)def test():    """Test this module.    A hodge podge of tests collected here, because they have too many    external dependencies for the regular test suite.    """    import sys    import getopt    opts, args = getopt.getopt(sys.argv[1:], 'd')    dl = 0    for o, a in opts:        if o == '-d': dl = dl + 1    host = 'www.python.org'    selector = '/'    if args[0:]: host = args[0]    if args[1:]: selector = args[1]    h = HTTP()    h.set_debuglevel(dl)    h.connect(host)    h.putrequest('GET', selector)    h.endheaders()    status, reason, headers = h.getreply()    print 'status =', status    print 'reason =', reason    print "read", len(h.getfile().read())    print    if headers:        for header in headers.headers: print header.strip()    print    # minimal test that code to extract host from url works    class HTTP11(HTTP):        _http_vsn = 11        _http_vsn_str = 'HTTP/1.1'    h = HTTP11('www.python.org')    h.putrequest('GET', 'http://www.python.org/~jeremy/')    h.endheaders()    h.getreply()    h.close()    if hasattr(socket, 'ssl'):        for host, selector in (('sourceforge.net', '/projects/python'),                               ):            print "https://%s%s" % (host, selector)            hs = HTTPS()            hs.set_debuglevel(dl)            hs.connect(host)            hs.putrequest('GET', selector)            hs.endheaders()            status, reason, headers = hs.getreply()            print 'status =', status            print 'reason =', reason            print "read", len(hs.getfile().read())            print            if headers:                for header in headers.headers: print header.strip()            printif __name__ == '__main__':    test()

⌨️ 快捷键说明

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