def unenvelope_or_raise_error(resp: httpx.Response) -> Dict: """ Director responses are enveloped If successful response, we un-envelop it and return data as a dict If error, it raise an HTTPException """ body = resp.json() assert "data" in body or "error" in body # nosec data = body.get("data") error = body.get("error") if codes.is_server_error(resp.status_code): logger.error( "director error %d [%s]: %s", resp.status_code, resp.reason_phrase, error, ) raise HTTPException(status.HTTP_503_SERVICE_UNAVAILABLE) if codes.is_client_error(resp.status_code): msg = error or resp.reason_phrase raise HTTPException(resp.status_code, detail=msg) return data or {}
def _process(cls, resp: Response) -> Optional[JSON]: # enveloped answer data, error = None, None try: body = resp.json() data, error = body.get("data"), body.get("error") except (json.JSONDecodeError, KeyError): logger.warning("Failed to unenvelop webserver response", exc_info=True) if codes.is_server_error(resp.status_code): logger.error( "webserver error %d [%s]: %s", resp.status_code, resp.reason_phrase, error, ) raise HTTPException(status.HTTP_503_SERVICE_UNAVAILABLE) if codes.is_client_error(resp.status_code): msg = error or resp.reason_phrase raise HTTPException(resp.status_code, detail=msg) return data
async def _dispatch_send( self, request: Request, *, timeout: float = None, retry_count: int = None, ): """ TODO: need better implementation for retry :param request: :param timeout: :param retry_count: """ attempts = 1 if request.method == "GET": attempts += (settings.SERVICE_CONNECTION_DEFAULT_RETRY_COUNT if retry_count is None else min( retry_count, int(settings.SERVICE_CONNECTION_MAX_RETRY_COUNT), )) for i in range(attempts): try: response = await self.client.send(request, timeout=timeout) if codes.is_server_error(response.status_code): response.raise_for_status() except (TransportError, HTTPStatusError, ConnectionResetError) as e: error_logger.debug(f"{str(e)} on attempt {i}") if i + 1 >= attempts: raise else: return response