def test_raises_exception_on_unsuccessful_request(self, requests_mock): """Tests that an exception is raised on an successful request.""" api_url = 'http://test/v1/' requests_mock.get('http://test/v1/path/to/item', status_code=404) api_client = APIClient(api_url) with pytest.raises(HTTPError) as excinfo: api_client.request('GET', 'path/to/item') assert excinfo.value.response.status_code == 404
def fetch_export_wins(match_ids, request=None): """ Queries the Export Wins API with the given list of match ids. Export Wins API takes either a single match id or comma separated list of match ids. """ if not all([ settings.EXPORT_WINS_SERVICE_BASE_URL, settings.EXPORT_WINS_HAWK_ID, settings.EXPORT_WINS_HAWK_KEY, ]): raise ImproperlyConfigured( 'The all EXPORT_WINS_SERVICE* setting must be set') match_ids_str = ','.join(list(map(str, match_ids))) api_client = APIClient( api_url=settings.EXPORT_WINS_SERVICE_BASE_URL, auth=HawkAuth(settings.EXPORT_WINS_HAWK_ID, settings.EXPORT_WINS_HAWK_KEY), raise_for_status=True, default_timeout=settings.DEFAULT_SERVICE_TIMEOUT, ) return api_client.request( 'GET', f'wins/match?match_id={match_ids_str}', timeout=3.0, )
class DataScienceCompanyAPIClient: """ Client for the data science DT07 reporting service. (See https://github.com/uktrade/dt07-reporting for more information.) This is used for retrieving company timeline data. """ def __init__(self): """ Initialises the client. The API URL and key are taken from settings. """ api_url = settings.DATA_SCIENCE_COMPANY_API_URL api_id = settings.DATA_SCIENCE_COMPANY_API_ID api_key = settings.DATA_SCIENCE_COMPANY_API_KEY if not all((api_url, api_id, api_key)): raise ImproperlyConfigured( 'Data science company API connection details not configured', ) timeout = settings.DATA_SCIENCE_COMPANY_API_TIMEOUT verify_responses = settings.DATA_SCIENCE_COMPANY_API_VERIFY_RESPONSES auth = HawkAuth(api_id, api_key, verify_response=verify_responses) self._api_client = APIClient(api_url, auth, default_timeout=timeout) def get_timeline_events_by_company_number(self, company_number): """Gets timeline events for a company using a company number.""" transformed_company_number = _transform_company_number(company_number) if not transformed_company_number: raise InvalidCompanyNumberError data = self._request( '/api/v1/company/events/', params={ 'companies_house_id': transformed_company_number, }, ) return _transform_events_response(data) def _request(self, path, **kwargs): try: response = self._api_client.request('get', path, **kwargs) except HTTPError as exc: if exc.response.status_code != status.HTTP_404_NOT_FOUND: event_id = client.captureException() raise APIException( f'Error communicating with the company timeline API. Error ' f'reference: {event_id}.', ) from exc return {} else: return response.json()
def test_successful_request(self, requests_mock): """Tests making a successful request.""" api_url = 'http://test/v1/' requests_mock.get('http://test/v1/path/to/item', status_code=200) api_client = APIClient(api_url) response = api_client.request('GET', 'path/to/item') assert response.status_code == 200 assert response.request.headers['Accept'] == APIClient.DEFAULT_ACCEPT assert response.request.timeout is None
def test_doesnt_raise_exception_on_unsuccessful_request_if_flag_is_false( self, requests_mock): """ Tests that no exception is raised on an successful request if the raise_for_status argument is False. """ api_url = 'http://test/v1/' requests_mock.get('http://test/v1/path/to/item', status_code=404) api_client = APIClient(api_url, raise_for_status=False) response = api_client.request('GET', 'path/to/item') assert response.status_code == 404
def test_omits_accept_if_none(self, requests_mock): """Tests that the Accept header is not overridden when accept=None is passed.""" api_url = 'http://test/v1/' requests_mock.get('http://test/v1/path/to/item', status_code=200) api_client = APIClient( api_url, auth=HTTPBasicAuth('user', 'password'), accept=None, ) response = api_client.request('GET', 'path/to/item') assert response.status_code == 200 assert response.request.headers['Accept'] == '*/*'
def test_zipkin_headers_are_forwarded(self, requests_mock): """Tests that zipkin headers from the origin request are forwarded.""" api_url = 'http://test/v1/' requests_mock.get('http://test/v1/path/to/item', status_code=200) request = Mock(headers={ 'x-b3-traceid': '123', 'x-b3-spanid': '456', }) api_client = APIClient(api_url, request=request) response = api_client.request( 'GET', 'path/to/item', ) assert request.headers.items() <= response.request.headers.items()
def test_can_specify_headers(self, requests_mock): """Tests that headers can be specified when making a request.""" api_url = 'http://test/v1/' requests_mock.get('http://test/v1/path/to/item', status_code=200) api_client = APIClient(api_url) headers = { 'Content-Type': 'application/json', 'User-Agent': 'test user agent', } response = api_client.request( 'GET', 'path/to/item', headers=headers, ) assert headers.items() <= response.request.headers.items()
def test_passes_through_arguments(self, requests_mock): """Tests that auth, accept and default_timeout are passed to the request.""" api_url = 'http://test/v1/' requests_mock.get('http://test/v1/path/to/item', status_code=200) api_client = APIClient( api_url, auth=HTTPBasicAuth('user', 'password'), accept='test-accept', default_timeout=10, ) response = api_client.request('GET', 'path/to/item') assert response.status_code == 200 assert response.request.headers['Accept'] == 'test-accept' assert response.request.timeout == 10
def test_can_override_timeout_per_request(self, requests_mock, default_timeout): """Tests that the timeout can be overridden for a specific request.""" api_url = 'http://test/v1/' requests_mock.get('http://test/v1/path/to/item', status_code=200) api_client = APIClient( api_url, auth=HTTPBasicAuth('user', 'password'), accept='test-accept', default_timeout=default_timeout, ) response = api_client.request('GET', 'path/to/item', timeout=20) assert response.status_code == 200 assert response.request.headers['Accept'] == 'test-accept' assert response.request.timeout == 20
def request_match_companies(json_body, request=None): """ Queries the company matching service with the given json_body. E.g.: { "descriptions": [ { "id": "1", "companies_house_id": "0921309", "duns_number": "d210" "company_name":"apple", "contact_email": "*****@*****.**", "cdms_ref": "782934", "postcode": "SW129RP" } ] } Note that the ID field typically the company UUID that is returned by the api for data mapping. ID and at least one of the following fields companies_house_id, duns_number, company_name, contact_email, cdms_ref and postcode are required. """ if not all([ settings.COMPANY_MATCHING_SERVICE_BASE_URL, settings.COMPANY_MATCHING_HAWK_ID, settings.COMPANY_MATCHING_HAWK_KEY, ]): raise ImproperlyConfigured( 'The all COMPANY_MATCHING_SERVICE_* setting must be set') api_client = APIClient( api_url=settings.COMPANY_MATCHING_SERVICE_BASE_URL, auth=HawkAuth(settings.COMPANY_MATCHING_HAWK_ID, settings.COMPANY_MATCHING_HAWK_KEY), raise_for_status=True, default_timeout=settings.DEFAULT_SERVICE_TIMEOUT, request=request, ) return api_client.request( 'POST', 'api/v1/company/match/', json=json_body, timeout=3.0, )
def _get_upstream_response(self, request): hawk_auth = HawkAuth( settings.ACTIVITY_STREAM_OUTGOING_ACCESS_KEY_ID, settings.ACTIVITY_STREAM_OUTGOING_SECRET_ACCESS_KEY, verify_response=False, ) api_client = APIClient( settings.ACTIVITY_STREAM_OUTGOING_URL, hawk_auth, raise_for_status=False, ) return api_client.request( request.method, '', data=request.body, headers={ 'Content-Type': request.content_type, }, )
def _request(method, path, response_serializer_class=None, request=None, **kwargs): """ Internal utility function to make a generic API request to Staff SSO. As this deals with authentication, this aims to be more robust than might be the case for other API requests. """ api_client = APIClient( settings.STAFF_SSO_BASE_URL, TokenAuth(settings.STAFF_SSO_AUTH_TOKEN, token_keyword='Bearer'), default_timeout=settings.STAFF_SSO_REQUEST_TIMEOUT, request=request, ) try: response = api_client.request(method, path, **kwargs) except APIBadGatewayException as exc: raise SSORequestError('SSO service unavailable') from exc except RequestException as exc: raise SSORequestError('SSO request failed', response=exc.response) from exc try: response_data = response.json() except ValueError as exc: raise SSORequestError('SSO response parsing failed') from exc if not response_serializer_class: return response_data try: serializer = response_serializer_class(data=response_data) serializer.is_valid(raise_exception=True) except serializers.ValidationError as exc: raise SSORequestError('SSO response validation failed') from exc return serializer.validated_data
def _get_upstream_response(self, request=None): hawk_auth = HawkAuth( settings.ACTIVITY_STREAM_OUTGOING_ACCESS_KEY_ID, settings.ACTIVITY_STREAM_OUTGOING_SECRET_ACCESS_KEY, verify_response=False, ) api_client = APIClient( api_url=settings.ACTIVITY_STREAM_OUTGOING_URL, auth=hawk_auth, request=request, raise_for_status=False, default_timeout=settings.DEFAULT_SERVICE_TIMEOUT, ) return api_client.request( request.method, '', data=request.body, headers={ 'Content-Type': request.content_type, }, )