"""Parent class for ows services.""" from typing import Any from typing import ClassVar from httpx import Response from lambdacommon.common_config import logger from owsclient import M2MTokenManager from owsclient import OwsClient from secrets_manager.python_ext import PythonSecretsManager from config import APPLICATION_NAME from config import ENVIRONMENT from config import OWS_CLIENT_TOKEN from config import TEST_ENVIRONMENT from src.exceptions import OwsServiceException from src.utils.constants import DEFAULT_HEADERS from src.utils.constants import RequestMethod class OwsService: """Ows parent class on which clients will inherit.""" _service: ClassVar[str] _secrets_manager: ClassVar[PythonSecretsManager] = PythonSecretsManager(region_name='us-east-1') _m2m_token_manager: ClassVar[M2MTokenManager] = M2MTokenManager( secrets_manager=_secrets_manager, environment=ENVIRONMENT, service_name=APPLICATION_NAME, ) _ows_client: ClassVar[OwsClient] = OwsClient( environment=ENVIRONMENT, service_name=APPLICATION_NAME, m2m_token_manager=_m2m_token_manager if ENVIRONMENT != TEST_ENVIRONMENT else None, ) @classmethod def get(cls, path: str) -> dict[str, Any]: """Make a GET request and return the response. Args: path (str): the url of the request. Returns: dict: a json response in the form of a dict. """ response = cls._ows_client.get(cls._service, path=path, headers=cls._get_request_headers()) return cls._process_request(path, RequestMethod.GET, response) @classmethod def put(cls, path: str, **body: str | int | None) -> dict[str, Any]: """Make a PUT request and return the response. Args: path (str): the url of the request. body: keyword arguments for the body of the request. Returns: dict: a json response in the form of a dict. """ response = cls._ows_client.put( cls._service, path=path, headers=cls._get_request_headers(), json=body ) return cls._process_request(path, RequestMethod.PUT, response, body) @classmethod def _get_request_headers(cls) -> dict[str, str]: """Get the headers for each request. Returns: dict[str, str]: Request headers. """ headers = {k: v for k, v in DEFAULT_HEADERS.items() if v is not None} if OWS_CLIENT_TOKEN: headers['authorization'] = f'Bearer {OWS_CLIENT_TOKEN}' return headers @classmethod def _process_request( cls, path: str, method: RequestMethod, response: Response, body: dict[str, str | int | None] | None = None, ) -> dict[str, Any]: """Process a request by logging it, checking the response status and returning it. Args: path (str): the path of the request. method (RequestMethod): the request method. response (Response): the response returned from the endpoint. body (dict | None): the body of the request being sent. Returns: dict: response data converted to json. """ headers = ' '.join([f'{h[0]}:{h[1]}' for h in DEFAULT_HEADERS.items()]) status = response.status_code body_contents = str(body) if body else '' text = response.text logger.info(f'{method} {cls._service} {path} ({headers}) {body_contents}') if response.status_code > 299: message = ( f'{cls._service} error: {status} response from ' f'{method} {path}{body_contents}: {text}' ) raise OwsServiceException(message, response.status_code) data = response.json() logger.info(str(data)) return data