def handle_exception(): """ Context manager translating network related exceptions to custom :mod:`~galaxy.api.errors`. """ try: yield except asyncio.TimeoutError: raise BackendTimeout() except aiohttp.ServerDisconnectedError: raise BackendNotAvailable() except aiohttp.ClientConnectionError: raise NetworkError() except aiohttp.ContentTypeError as error: raise UnknownBackendResponse(error.message) except aiohttp.ClientResponseError as error: if error.status == HTTPStatus.UNAUTHORIZED: raise AuthenticationRequired(error.message) if error.status == HTTPStatus.FORBIDDEN: raise AccessDenied(error.message) if error.status == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable(error.message) if error.status == HTTPStatus.TOO_MANY_REQUESTS: raise TooManyRequests(error.message) if error.status >= 500: raise BackendError(error.message) if error.status >= 400: logger.warning("Got status %d while performing %s request for %s", error.status, error.request_info.method, str(error.request_info.url)) raise UnknownError(error.message) except aiohttp.ClientError as e: logger.exception("Caught exception while performing request") raise UnknownError(repr(e))
async def request(self, method, url, *args, **kwargs): try: response = await self._session.request(method, url, *args, **kwargs) except asyncio.TimeoutError: raise BackendTimeout() except aiohttp.ServerDisconnectedError: raise BackendNotAvailable() except aiohttp.ClientConnectionError: raise NetworkError() except aiohttp.ContentTypeError: raise UnknownBackendResponse() except aiohttp.ClientError: logging.exception( "Caught exception while running {} request for {}".format( method, url)) raise UnknownError() if response.status == HTTPStatus.UNAUTHORIZED: raise AuthenticationRequired() if response.status == HTTPStatus.FORBIDDEN: raise AccessDenied() if response.status == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable() if response.status == HTTPStatus.TOO_MANY_REQUESTS: raise TooManyRequests() if response.status >= 500: raise BackendError() if response.status >= 400: logging.warning( "Got status {} while running {} request for {}".format( response.status, method, url)) raise UnknownError() return response
async def test_backend_error(_patch_plugin): game_id = '121' error = BackendNotAvailable() game_times = [GameTime(game_id, None, None)] plugin = _patch_plugin(game_times) plugin.client.get_game_stats = AsyncMock(side_effect=error) context = await plugin.prepare_game_times_context( [gt.game_id for gt in game_times]) assert context == {}
def handle_status_code(status_code): if status_code == HTTPStatus.UNAUTHORIZED: raise AuthenticationRequired() if status_code == HTTPStatus.FORBIDDEN: raise AccessDenied() if status_code == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable() if status_code >= 500: raise BackendError() if status_code >= 400: raise UnknownError()
async def do_request(self, method, url, data=None, json=True, headers=None, ignore_failure=False): loop = asyncio.get_event_loop() if not headers: headers = self._authentication_client.session.headers try: if data is None: data = {} params = { "method": method, "url": url, "data": data, "timeout": self._authentication_client.timeout, "headers": headers } try: response = await loop.run_in_executor( None, functools.partial( self._authentication_client.session.request, **params)) except requests.Timeout: raise BackendTimeout() if not ignore_failure: if response.status_code == HTTPStatus.UNAUTHORIZED: raise AuthenticationRequired() if response.status_code == HTTPStatus.FORBIDDEN: raise AccessDenied() if response.status_code == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable() if response.status_code >= 500: raise BackendError() if response.status_code >= 400: raise UnknownError() if json: return response.json() else: return response except Exception as e: log.exception( f"Request exception: {str(e)}; url: {url}, method: {method}, data: {data}, headers: {headers}" ) raise
async def test_refresh_token_independent_failure(http_request, http_client, create_json_response): auth_lost = MagicMock() http_client.set_auth_lost_callback(auth_lost) http_request.return_value = create_json_response({"access_token": "token"}) await http_client.authenticate({}) http_request.assert_called_once() http_request.reset_mock() http_request.side_effect = [AccessDenied(), BackendNotAvailable()] with pytest.raises(BackendNotAvailable): await http_client.get("http://test.com") assert http_request.call_count == 2 auth_lost.assert_not_called()
async def _do_request(self, method, url, *args, **kwargs): loop = asyncio.get_running_loop() r = await loop.run_in_executor(None, functools.partial(self.session.request, method, url, *args, **kwargs)) log.info(f"{r.status_code}: response from endpoint {url}") if r.status_code in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN): raise AccessDenied() if r.status_code == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable() if r.status_code >= 500: raise BackendError() if r.status_code >= 400: raise UnknownError() j = r.json() # all ubi endpoints return jsons return j
async def _request(self, method, *args, **kwargs): try: response = await self._session.request(method, *args, **kwargs) except asyncio.TimeoutError: raise BackendTimeout() except aiohttp.ClientConnectionError: raise NetworkError() logging.debug(f"Request response status: {response.status}") if response.status == HTTPStatus.UNAUTHORIZED: raise AuthenticationRequired() if response.status == HTTPStatus.FORBIDDEN: raise AccessDenied() if response.status == HTTPStatus.SERVICE_UNAVAILABLE: raise BackendNotAvailable() if response.status >= 500: raise BackendError() if response.status >= 400: raise UnknownError() return response
async_raise(websockets.ConnectionClosedOK(1000, ""), 10) ] protocol_client.close.return_value = async_return_value(None) protocol_client.wait_closed.return_value = async_return_value(None) websocket.close.return_value = async_return_value(None) websocket.wait_closed.return_value = async_return_value(None) await client.run() assert servers_cache.get.call_count == 2 assert protocol_client.authenticate.call_count == 2 assert protocol_client.run.call_count == 2 @pytest.mark.asyncio @pytest.mark.parametrize( "exception", [BackendNotAvailable(), BackendTimeout(), BackendError(), NetworkError()]) async def test_servers_cache_retry(client, protocol_client, backend_client, servers_cache, websocket, mocker, exception): servers_cache.get.side_effect = [ async_raise(exception), async_return_value(["wss://abc.com/websocket"]) ] sleep = mocker.patch("protocol.websocket_client.asyncio.sleep", side_effect=lambda x: async_return_value(None)) backend_client.get_authentication_data.return_value = STEAM_ID, ACCOUNT_NAME, TOKEN protocol_client.authenticate.return_value = async_return_value(None) protocol_client.run.return_value = async_raise(
async_raise(websockets.ConnectionClosedError(1002, ""), 10), async_raise(websockets.ConnectionClosedOK(1000, ""), 10) ] protocol_client.close.return_value = async_return_value(None) protocol_client.wait_closed.return_value = async_return_value(None) websocket.close.return_value = async_return_value(None) websocket.wait_closed.return_value = async_return_value(None) await client.run() assert servers_cache.get.call_count == 2 assert protocol_client.authenticate.call_count == 2 assert protocol_client.run.call_count == 2 @pytest.mark.asyncio @pytest.mark.parametrize("exception", [ BackendNotAvailable(), BackendTimeout(), BackendError(), NetworkError() ]) async def test_servers_cache_retry( client, protocol_client, backend_client, servers_cache, websocket, mocker, exception ): servers_cache.get.side_effect = [ async_raise(exception), async_return_value(["wss://abc.com/websocket"]) ] sleep = mocker.patch("protocol.websocket_client.asyncio.sleep", side_effect=lambda x: async_return_value(None)) backend_client.get_authentication_data.return_value = STEAM_ID, ACCOUNT_NAME, TOKEN protocol_client.authenticate.return_value = async_return_value(None) protocol_client.run.return_value = async_raise(websockets.ConnectionClosedOK(1000, ""), 10) await client.run() sleep.assert_any_call(RECONNECT_INTERVAL_SECONDS)