Beispiel #1
0
    def __init__(self, url, data=None, method=None, timeout=30, **kwargs):
        self.last_read = time.time()
        self.timeout = timeout
        self.set_terminator('\r\n\r\n')
        # parse the url and set everything up
        self.url = url
        self.parsed = parsed = urlparse.urlparse(url)
        if parsed.scheme not in ('http', 'https'):
            raise httplib.UnknownProtocol("Can only access http urls")
        self.method = None
        self.established = parsed.scheme == 'http'
        if method and method.upper() in ('GET', 'POST'):
            self.method = method.upper()
        else:
            self.method = 'POST' if data is not None else 'GET'
        self.callbacks = kwargs

        # prepare the http request itself
        post_body = urllib.urlencode(data) if data is not None else None
        host, _, port = parsed.netloc.partition(':')
        http = httplib.HTTPConnection(host)
        http.sock = StringBuffer()
        path = parsed.path
        if parsed.params:
            path += ';' + parsed.params
        if parsed.query:
            path += '?' + parsed.query
        http.request(self.method, path, post_body)

        # connect to the host asynchronously
        asynchat.async_chat.__init__(self)
        self.push(http.sock.getvalue())
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        port = int(port, 10) if port else PORTS[parsed.scheme]
        self.connect((host, port))
    def __init__(self, request_handler=TestingHTTPRequestHandler,
                 protocol_version=None):
        """Constructor.

        :param request_handler: a class that will be instantiated to handle an
            http connection (one or several requests).

        :param protocol_version: if specified, will override the protocol
            version of the request handler.
        """
        # Depending on the protocol version, we will create the approriate
        # server
        if protocol_version is None:
            # Use the request handler one
            proto_vers = request_handler.protocol_version
        else:
            # Use our own, it will be used to override the request handler
            # one too.
            proto_vers = protocol_version
        # Get the appropriate server class for the required protocol
        serv_cls = self.http_server_class.get(proto_vers, None)
        if serv_cls is None:
            raise httplib.UnknownProtocol(proto_vers)
        self.host = 'localhost'
        self.port = 0
        super(HttpServer, self).__init__((self.host, self.port),
                                         serv_cls,
                                         request_handler)
        self.protocol_version = proto_vers
        # Allows tests to verify number of GET requests issued
        self.GET_request_nb = 0
        self._http_base_url = None
        self.logs = []
Beispiel #3
0
    def _read_status(self, line):
        version = None
        status = None
        reason = None
        # Initialize with Simple-Response defaults
        if not line:
            # Presumably, the server closed the connection before
            # sending a valid response.
            raise httplib.BadStatusLine(line)
        try:
            [version, status, reason] = line.split(None, 2)
        except ValueError:
            try:
                [version, status] = line.split(None, 1)
                reason = ""
            except ValueError:
                # empty version will cause next test to fail and status
                # will be treated as 0.9 response.
                version = ""
        if not version.startswith('HTTP/'):
            print repr(line)
            errinfo = "error http status"
            raise socket.error(errinfo)

        # The status code is a three-digit number
        try:
            status = int(status)
            if status < 100 or status > 999:
                raise httplib.BadStatusLine(line)
        except ValueError:
            raise httplib.BadStatusLine(line)

        self.status = status
        self.reason = reason.strip()
        if version == 'HTTP/1.0':
            self.version = 10
        elif version.startswith('HTTP/1.'):
            self.version = 11
        elif version == 'HTTP/0.9':
            self.version = 9
        else:
            raise httplib.UnknownProtocol(version)
Beispiel #4
0
def _generic_proxytunnel(self):
    proxyheaders = dict([(x, self.headers[x]) for x in self.headers
                         if x.lower().startswith('proxy-')])
    self.send('CONNECT %s HTTP/1.0\r\n' % self.realhostport)
    for header in proxyheaders.iteritems():
        self.send('%s: %s\r\n' % header)
    self.send('\r\n')

    # majority of the following code is duplicated from
    # httplib.HTTPConnection as there are no adequate places to
    # override functions to provide the needed functionality
    res = self.response_class(self.sock,
                              strict=self.strict,
                              method=self._method)

    while True:
        version, status, reason = res._read_status()
        if status != httplib.CONTINUE:
            break
        while True:
            skip = res.fp.readline().strip()
            if not skip:
                break
    res.status = status
    res.reason = reason.strip()

    if res.status == 200:
        while True:
            line = res.fp.readline()
            if line == '\r\n':
                break
        return True

    if version == 'HTTP/1.0':
        res.version = 10
    elif version.startswith('HTTP/1.'):
        res.version = 11
    elif version == 'HTTP/0.9':
        res.version = 9
    else:
        raise httplib.UnknownProtocol(version)

    if res.version == 9:
        res.length = None
        res.chunked = 0
        res.will_close = 1
        res.msg = httplib.HTTPMessage(cStringIO.StringIO())
        return False

    res.msg = httplib.HTTPMessage(res.fp)
    res.msg.fp = None

    # are we using the chunked-style of transfer encoding?
    trenc = res.msg.getheader('transfer-encoding')
    if trenc and trenc.lower() == "chunked":
        res.chunked = 1
        res.chunk_left = None
    else:
        res.chunked = 0

    # will the connection close at the end of the response?
    res.will_close = res._check_close()

    # do we have a Content-Length?
    # NOTE: RFC 2616, section 4.4, #3 says we ignore this if
    # transfer-encoding is "chunked"
    length = res.msg.getheader('content-length')
    if length and not res.chunked:
        try:
            res.length = int(length)
        except ValueError:
            res.length = None
        else:
            if res.length < 0:  # ignore nonsensical negative lengths
                res.length = None
    else:
        res.length = None

    # does the body have a fixed length? (of zero)
    if (status == httplib.NO_CONTENT or status == httplib.NOT_MODIFIED
            or 100 <= status < 200 or  # 1xx codes
            res._method == 'HEAD'):
        res.length = 0

    # if the connection remains open, and we aren't using chunked, and
    # a content-length was not provided, then assume that the connection
    # WILL close.
    if (not res.will_close and not res.chunked and res.length is None):
        res.will_close = 1

    self.proxyres = res

    return False
Beispiel #5
0
    def begin(self):
        if self.msg is not None:
            # we've already started reading the response
            return

        # read until we get a non-100 response
        while True:
            version, status, reason = self._read_status()
            if status != httplib.CONTINUE:
                break
            # skip the header from the 100 response
            while True:
                skip = self.fp.readline(httplib._MAXLINE + 1)
                if len(skip) > httplib._MAXLINE:
                    raise httplib.LineTooLong("header line")
                skip = skip.strip()
                if not skip:
                    break
                if self.debuglevel > 0:
                    print "header:", skip

        self.status = status
        self.reason = reason.strip()
        if version == 'HTTP/1.0':
            self.version = 10
        elif version.startswith('HTTP/1.'):
            self.version = 11  # use HTTP/1.1 code for HTTP/1.x where x>=1
        elif version == 'HTTP/0.9':
            self.version = 9
        else:
            raise httplib.UnknownProtocol(version)

        if self.version == 9:
            self.length = None
            self.chunked = 0
            self.will_close = 1
            self.msg = httplib.HTTPMessage(StringIO())
            return

        self.msg = httplib.HTTPMessage(self.fp, 0)
        if self.debuglevel > 0:
            for hdr in self.msg.headers:
                print "header:", hdr,

        # don't let the msg keep an fp
        self.msg.fp = None

        # are we using the chunked-style of transfer encoding?
        tr_enc = self.msg.getheader('transfer-encoding')
        if tr_enc and tr_enc.lower() == "chunked":
            self.chunked = 1
            self.chunk_left = None
        else:
            self.chunked = 0

        # will the connection close at the end of the response?
        self.will_close = self._check_close()

        # do we have a Content-Length?
        # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
        length = self._get_content_length()
        if length and not self.chunked:
            try:
                self.length = int(length)
            except (ValueError, TypeError):
                self.length = None
            else:
                if self.length < 0:  # ignore nonsensical negative lengths
                    self.length = None
        else:
            self.length = None

        # does the body have a fixed length? (of zero)
        if (status == NO_CONTENT or status == httplib.NOT_MODIFIED
                or 100 <= status < 200 or  # 1xx codes
                self._method == 'HEAD'):
            self.length = 0

        # if the connection remains open, and we aren't using chunked, and
        # a content-length was not provided, then assume that the connection
        # WILL close.
        if not self.will_close and \
           not self.chunked and \
           self.length is None:
            self.will_close = 1