Пример #1
0
    def test_host_fallback(self):
        ably = AblyRest(token="foo")
        self.assertIn('http_max_retry_count', ably.http.CONNECTION_RETRY_DEFAULTS)

        def make_url(host):
            base_url = "%s://%s:%d" % (ably.http.preferred_scheme,
                                       host,
                                       ably.http.preferred_port)
            return urljoin(base_url, '/')

        with mock.patch('requests.Request', wraps=requests.Request) as request_mock:
            with mock.patch('requests.sessions.Session.send',
                            side_effect=requests.exceptions.RequestException) as send_mock:
                with self.assertRaises(requests.exceptions.RequestException):
                    ably.http.make_request('GET', '/', skip_auth=True)

                self.assertEqual(
                    send_mock.call_count,
                    ably.http.CONNECTION_RETRY_DEFAULTS['http_max_retry_count'])

                expected_urls_set = set([
                    make_url(host)
                    for host in ([ably.http.preferred_host] +
                                 Defaults.get_fallback_rest_hosts(Options()))
                ])
                for ((__, url), ___) in request_mock.call_args_list:
                    self.assertIn(url, expected_urls_set)
                    expected_urls_set.remove(url)
Пример #2
0
    def test_host_fallback(self):
        ably = AblyRest(token="foo")
        self.assertIn('http_max_retry_count',
                      ably.http.CONNECTION_RETRY_DEFAULTS)

        def make_url(host):
            base_url = "%s://%s:%d" % (ably.http.preferred_scheme, host,
                                       ably.http.preferred_port)
            return urljoin(base_url, '/')

        with mock.patch('requests.Request',
                        wraps=requests.Request) as request_mock:
            with mock.patch('requests.sessions.Session.send',
                            side_effect=requests.exceptions.RequestException
                            ) as send_mock:
                with self.assertRaises(requests.exceptions.RequestException):
                    ably.http.make_request('GET', '/', skip_auth=True)

                self.assertEqual(
                    send_mock.call_count, ably.http.
                    CONNECTION_RETRY_DEFAULTS['http_max_retry_count'])

                expected_urls_set = set([
                    make_url(host)
                    for host in ([ably.http.preferred_host] +
                                 Defaults.get_fallback_rest_hosts(Options()))
                ])
                for ((__, url), ___) in request_mock.call_args_list:
                    self.assertIn(url, expected_urls_set)
                    expected_urls_set.remove(url)
Пример #3
0
    def make_request(self, method, path, headers=None, body=None,
                     native_data=None, skip_auth=False, timeout=None):
        fallback_hosts = Defaults.get_fallback_rest_hosts(self.__options)
        if fallback_hosts:
            fallback_hosts.insert(0, self.preferred_host)
            fallback_hosts = itertools.cycle(fallback_hosts)
        if native_data is not None and body is not None:
            raise ValueError("make_request takes either body or native_data")
        elif native_data is not None:
            body = self.dump_body(native_data)
        if body:
            all_headers = HttpUtils.default_post_headers(
                self.options.use_binary_protocol)
        else:
            all_headers = HttpUtils.default_get_headers(
                self.options.use_binary_protocol)

        if not skip_auth:
            if self.auth.auth_mechanism == Auth.Method.BASIC and self.preferred_scheme.lower() == 'http':
                raise AblyException(
                    "Cannot use Basic Auth over non-TLS connections",
                    401,
                    40103)
            all_headers.update(self.auth._get_auth_headers())
        if headers:
            all_headers.update(headers)

        http_open_timeout = self.http_open_timeout
        http_request_timeout = self.http_request_timeout
        if fallback_hosts:
            http_max_retry_count = self.http_max_retry_count
        else:
            http_max_retry_count = 1
        http_max_retry_duration = self.http_max_retry_duration
        requested_at = time.time()
        for retry_count in range(http_max_retry_count):
            host = next(fallback_hosts) if fallback_hosts else self.preferred_host
            if self.options.environment:
                host = self.options.environment + '-' + host

            base_url = "%s://%s:%d" % (self.preferred_scheme,
                                       host,
                                       self.preferred_port)
            url = urljoin(base_url, path)
            request = requests.Request(method, url, data=body, headers=all_headers)
            prepped = self.__session.prepare_request(request)
            try:
                response = self.__session.send(
                    prepped,
                    timeout=(http_open_timeout,
                             http_request_timeout))
            except Exception as e:
                # Need to catch `Exception`, see:
                # https://github.com/kennethreitz/requests/issues/1236#issuecomment-133312626

                # if last try or cumulative timeout is done, throw exception up
                time_passed = time.time() - requested_at
                if retry_count == http_max_retry_count - 1 or \
                   time_passed > http_max_retry_duration:
                    raise e
            else:
                try:
                    AblyException.raise_for_response(response)
                    return Response(response)
                except AblyException as e:
                    if not e.is_server_error:
                        raise e