diff --git a/infrastructure/abri/abri_client.py b/infrastructure/abri/abri_client.py index a0cedd5f7..72a3c4767 100644 --- a/infrastructure/abri/abri_client.py +++ b/infrastructure/abri/abri_client.py @@ -39,51 +39,66 @@ class AbriClient: ("resource_group", RESOURCE_GROUP), ], ) + if isinstance(outcome, AbriRequestRejected): return outcome + return self._parse_job_logged(outcome) def _exchange( self, request_type: str, parameters: List[Tuple[str, str]] ) -> Union[ET.Element, AbriRequestRejected]: - """Send one relay request; return the success root or the typed rejection. - - Shared by all four relay request types: transport failures raise - AbriTransportError, ambiguous bodies raise AbriResponseParseError, and - only a well-formed false body becomes a rejection. - """ - body = serialise_relay_request( + envelope = serialise_relay_request( request_type=request_type, parameters=parameters, username=self._config.username, password=self._config.password, ) + + reply = self._parse_reply(self._post(envelope)) + + if self._is_failure_document(reply): + return self._parse_rejection(reply) + + return reply + + def _post(self, envelope: bytes) -> bytes: try: - response = self._session.post(self._config.endpoint_url, data=body) + response = self._session.post(self._config.endpoint_url, data=envelope) response.raise_for_status() except requests.RequestException as error: raise AbriTransportError(str(error)) from error + + return response.content + + @staticmethod + def _parse_reply(body: bytes) -> ET.Element: try: - root = ET.fromstring(response.content) + return ET.fromstring(body) except ET.ParseError as error: raise AbriResponseParseError(str(error)) from error - if root.tag == "response": - return self._parse_rejection(root) - return root + + @staticmethod + def _is_failure_document(reply: ET.Element) -> bool: + return reply.tag == "response" @staticmethod def _parse_job_logged(root: ET.Element) -> JobLogged: job_logged = root.find("Jobs/Job_logged") + if job_logged is None: raise AbriResponseParseError( "Job_logged element missing from relay response" ) + job_no = job_logged.get("job_no") logged_info = job_logged.get("logged_info") + if job_no is None or logged_info is None: raise AbriResponseParseError( "Job_logged element missing job_no or logged_info" ) + return JobLogged(job_no=job_no, logged_info=logged_info) @staticmethod @@ -91,6 +106,8 @@ class AbriClient: success = root.findtext("success") code = root.findtext("code") message = root.findtext("message") + if success != "false" or code is None or message is None: raise AbriResponseParseError("malformed relay failure response") + return AbriRequestRejected(code=code, message=message)