Пример #1
0
def putrequest(self, method, url, skip_host=False, skip_accept_encoding=False):
    '''Send a request to the server.

    This is mostly a regurgitation of CPython's HTTPConnection.putrequest,
    but fixed up so we can still send arbitrary bytes in the request line
    on py3. See also: https://bugs.python.org/issue36274

    To use, swap out a HTTP(S)Connection's putrequest with something like::

       conn.putrequest = putrequest.__get__(conn)

    :param method: specifies an HTTP request method, e.g. 'GET'.
    :param url: specifies the object being requested, e.g. '/index.html'.
    :param skip_host: if True does not add automatically a 'Host:' header
    :param skip_accept_encoding: if True does not add automatically an
       'Accept-Encoding:' header
    '''
    # (Mostly) inline the HTTPConnection implementation; just fix it
    # so we can send non-ascii request lines. For comparison, see
    # https://github.com/python/cpython/blob/v2.7.16/Lib/httplib.py#L888-L1003
    # and https://github.com/python/cpython/blob/v3.7.2/
    # Lib/http/client.py#L1061-L1183
    if self._HTTPConnection__response \
            and self._HTTPConnection__response.isclosed():
        self._HTTPConnection__response = None

    if self._HTTPConnection__state == http_client._CS_IDLE:
        self._HTTPConnection__state = http_client._CS_REQ_STARTED
    else:
        raise http_client.CannotSendRequest(self._HTTPConnection__state)

    self._method = method
    if not url:
        url = '/'
    self._path = url
    request = '%s %s %s' % (method, url, self._http_vsn_str)
    if not isinstance(request, bytes):
        # This choice of encoding is the whole reason we copy/paste from
        # cpython. When making backend requests, it should never be
        # necessary; however, we have some functional tests that want
        # to send non-ascii bytes.
        # TODO: when https://bugs.python.org/issue36274 is resolved, make
        # sure we fix up our API to match whatever upstream chooses to do
        self._output(request.encode('latin1'))
    else:
        self._output(request)

    if self._http_vsn == 11:
        if not skip_host:
            netloc = ''
            if url.startswith('http'):
                nil, netloc, nil, nil, nil = urllib.parse.urlsplit(url)

            if netloc:
                try:
                    netloc_enc = netloc.encode("ascii")
                except UnicodeEncodeError:
                    netloc_enc = netloc.encode("idna")
                self.putheader('Host', netloc_enc)
            else:
                if self._tunnel_host:
                    host = self._tunnel_host
                    port = self._tunnel_port
                else:
                    host = self.host
                    port = self.port

                try:
                    host_enc = host.encode("ascii")
                except UnicodeEncodeError:
                    host_enc = host.encode("idna")

                if host.find(':') >= 0:
                    host_enc = b'[' + host_enc + b']'

                if port == self.default_port:
                    self.putheader('Host', host_enc)
                else:
                    host_enc = host_enc.decode("ascii")
                    self.putheader('Host', "%s:%s" % (host_enc, port))

        if not skip_accept_encoding:
            self.putheader('Accept-Encoding', 'identity')
Пример #2
0
 def side_effect(mo, **kwargs):
     self.assertEqual(managed_object, mo._type)
     self.assertEqual(managed_object, mo.value)
     raise httplib.CannotSendRequest()
Пример #3
0
    def _do_request(self,
                    method,
                    path,
                    query_params,
                    body,
                    maximum_redirects,
                    extra_headers=None):
        full_uri = path
        if query_params is not None:
            full_uri = "%s?%s" % (path, urlencode(query_params))
        headers = self._headers.copy()
        if extra_headers is not None:
            headers.update(extra_headers)
        local_connection = False

        try:
            if logger.is_debugging():
                logger.debug("Request: %s %s" % (method, full_uri))
                logger.debug("Headers:")
                for key, value in headers.items():
                    logger.debug("--> %s: %s" % (key, value))

            # if we weren't called under a `with` statement, we'll need to manage the
            # connection here.
            if self._conn is None:
                self.__enter__()
                local_connection = True

            try:
                self._conn.request(method, full_uri, body, headers)

                response = self._conn.getresponse()
                response_body = response.read().decode("utf-8").strip()

                if logger.is_debugging():
                    logger.debug("Response: %s %s" %
                                 (response.status, response.reason))
                    logger.debug("Headers:")
                    for key, value in response.getheaders():
                        logger.debug("--> %s: %s" % (key, value))
                    logger.debug("--> %s" % response_body)
            finally:
                if local_connection:
                    self.__exit__()

            # Handle any redirects.
            if 300 <= response.status < 400:
                if maximum_redirects == 0:
                    raise http.CannotSendRequest("Too many redirects")

                location = response.getheader("Location")
                next_url = urljoin(self._url.geturl(), location)

                logger.debug("--> Redirected to: %s" % next_url)

                return self._do_request(
                    method,
                    next_url,
                    query_params,
                    body,
                    maximum_redirects - 1,
                    extra_headers,
                )

            self._handle_set_cookie(response)

            return self._tweak_response(
                HTTPResponse(full_uri, response=response, body=response_body))
        except (
                http.HTTPException,
                ssl.CertificateError,
                IOError,
                OSError,
                socket.error,
                socket.herror,
                socket.gaierror,
                socket.timeout,
        ) as exception:
            logger.debug("An exception occurred processing the HTTP request.",
                         exc_info=True)
            return HTTPResponse(full_uri, exception=exception)