Пример #1
0
    def http_request(cls, url, method='GET', body=None, headers=None):
        """Make an HTTP request with the given method to the given URL,
        returning the resulting `http_client.HTTPResponse` instance.

        If the `body` argument is a `Resource` instance, it is serialized
        to XML by calling its `to_element()` method before submitting it.
        Requests are authenticated per the Recurly API specification
        using the ``recurly.API_KEY`` value for the API key.

        Requests and responses are logged at the ``DEBUG`` level to the
        ``recurly.http.request`` and ``recurly.http.response`` loggers
        respectively.

        """

        if recurly.API_KEY is None:
            raise recurly.UnauthorizedError('recurly.API_KEY not set')

        headers = {} if headers is None else dict(headers)
        headers.setdefault('Accept', 'application/xml')
        headers.update({'User-Agent': recurly.USER_AGENT})
        headers['X-Api-Version'] = recurly.api_version()
        headers['Authorization'] = 'Basic %s' % base64.b64encode(
            six.b('%s:' % recurly.API_KEY)).decode()

        if isinstance(body, Resource):
            body = ElementTree.tostring(body.to_element(), encoding='UTF-8')
            headers['Content-Type'] = 'application/xml; charset=utf-8'
        if method in ('POST', 'PUT') and body is None:
            headers['Content-Length'] = '0'

        print(body)
        resp = requests.get(url, headers=headers)
        print(resp)

        resp_headers = resp.headers

        recurly.cache_rate_limit_headers(resp_headers)

        return resp
Пример #2
0
    def http_request(cls, url, method='GET', body=None, headers=None):
        """Make an HTTP request with the given method to the given URL,
        returning the resulting `http_client.HTTPResponse` instance.

        If the `body` argument is a `Resource` instance, it is serialized
        to XML by calling its `to_element()` method before submitting it.
        Requests are authenticated per the Recurly API specification
        using the ``recurly.API_KEY`` value for the API key.

        Requests and responses are logged at the ``DEBUG`` level to the
        ``recurly.http.request`` and ``recurly.http.response`` loggers
        respectively.

        """

        if recurly.API_KEY is None:
            raise recurly.UnauthorizedError('recurly.API_KEY not set')

        is_non_ascii = lambda s: any(ord(c) >= 128 for c in s)

        if is_non_ascii(recurly.API_KEY) or is_non_ascii(recurly.SUBDOMAIN):
            raise recurly.ConfigurationError("""Setting API_KEY or SUBDOMAIN to
                    unicode strings may cause problems. Please use strings.
                    Issue described here:
                    https://gist.github.com/maximehardy/d3a0a6427d2b6791b3dc"""
                                             )

        urlparts = urlsplit(url)
        connection_options = {}
        if recurly.SOCKET_TIMEOUT_SECONDS:
            connection_options['timeout'] = recurly.SOCKET_TIMEOUT_SECONDS
        if urlparts.scheme != 'https':
            connection = http_client.HTTPConnection(urlparts.netloc,
                                                    **connection_options)
        elif recurly.CA_CERTS_FILE is None:
            connection = http_client.HTTPSConnection(urlparts.netloc,
                                                     **connection_options)
        else:
            connection_options['context'] = ssl.create_default_context(
                cafile=recurly.CA_CERTS_FILE)
            connection = http_client.HTTPSConnection(urlparts.netloc,
                                                     **connection_options)

        headers = {} if headers is None else dict(headers)
        headers.setdefault('Accept', 'application/xml')
        headers.update({'User-Agent': recurly.USER_AGENT})
        headers['X-Api-Version'] = recurly.api_version()
        headers['Authorization'] = 'Basic %s' % base64.b64encode(
            six.b('%s:' % recurly.API_KEY)).decode()

        log = logging.getLogger('recurly.http.request')
        if log.isEnabledFor(logging.DEBUG):
            log.debug("%s %s HTTP/1.1", method, url)
            for header, value in six.iteritems(headers):
                if header == 'Authorization':
                    value = '<redacted>'
                log.debug("%s: %s", header, value)
            log.debug('')
            if method in ('POST', 'PUT') and body is not None:
                if isinstance(body, Resource):
                    log.debug(body.as_log_output())
                else:
                    log.debug(body)

        if isinstance(body, Resource):
            body = ElementTree.tostring(body.to_element(), encoding='UTF-8')
            headers['Content-Type'] = 'application/xml; charset=utf-8'
        if method in ('POST', 'PUT') and body is None:
            headers['Content-Length'] = '0'
        connection.request(method, url, body, headers)
        resp = connection.getresponse()

        resp_headers = cls.headers_as_dict(resp)

        log = logging.getLogger('recurly.http.response')
        if log.isEnabledFor(logging.DEBUG):
            log.debug("HTTP/1.1 %d %s", resp.status, resp.reason)
            log.debug(resp_headers)
            log.debug('')

        recurly.cache_rate_limit_headers(resp_headers)

        return resp
Пример #3
0
    def __enter__(self):
        self.request_context = mock.patch.object(http_client.HTTPConnection, 'request')
        self.request_context.return_value = None
        self.request_mock = self.request_context.__enter__()

        self.fixture_file = open(join(dirname(__file__), 'fixtures', self.fixture), 'rb')

        # Read through the request.
        preamble_line = self.fixture_file.readline().strip()
        try:
            self.method, self.uri, http_version = preamble_line.split(None, 2)
            self.method = self.method.decode()
            self.uri = self.uri.decode()
        except ValueError:
            raise ValueError("Couldn't parse preamble line from fixture file %r; does it have a fixture in it?"
                % self.fixture)

        # Read request headers
        def read_headers(fp):
            while True:
                try:
                    line = fp.readline()
                except EOFError:
                    return
                if not line or line == six.b('\n'):
                    return
                yield line

        if six.PY2:
            msg = http_client.HTTPMessage(self.fixture_file, 0)
            self.headers = dict((k, v.strip()) for k, v in (header.split(':', 1) for header in msg.headers))
        else:
            # http.client.HTTPMessage doesn't have importing headers from file
            msg = http_client.HTTPMessage()
            headers = email.message_from_bytes(six.b('').join(read_headers(self.fixture_file)))
            self.headers = dict((k, v.strip()) for k, v in headers._headers)
            # self.headers = {k: v for k, v in headers._headers}
        msg.fp = None

        # Read through to the vertical space.
        def nextline(fp):
            while True:
                try:
                    line = fp.readline()
                except EOFError:
                    return
                if not line or line.startswith(six.b('\x16')):
                    return
                yield line

        body = six.b('').join(nextline(self.fixture_file))  # exhaust the request either way
        self.body = None
        if self.method in ('PUT', 'POST'):
            if 'Content-Type' in self.headers:
                if 'application/xml' in self.headers['Content-Type']:
                    self.body = xml(body)
                else:
                    self.body = body

        # Set up the response returner.
        sock = mock.Mock()
        sock.makefile = mock.Mock(return_value=self.fixture_file)
        response = http_client.HTTPResponse(sock, method=self.method)
        response.begin()


        self.response_context = mock.patch.object(http_client.HTTPConnection, 'getresponse', lambda self: response)
        self.response_mock = self.response_context.__enter__()

        recurly.cache_rate_limit_headers(self.headers)

        return self