import requests from flask import current_app class DocumentDownloadError(Exception): def __init__(self, message, status_code): super().__init__(message, status_code) self.message = message self.status_code = status_code @classmethod def from_exception(cls, e): message = e.response.json()["error"] status_code = e.response.status_code return cls(message, status_code) class DocumentDownloadClient: def init_app(self, app): self.api_host = app.config["DOCUMENT_DOWNLOAD_API_HOST"] self.auth_token = app.config["DOCUMENT_DOWNLOAD_API_KEY"] def get_upload_url(self, service_id): return "{}/services/{}/documents".format(self.api_host, service_id) def upload_document(self, service_id, file_contents, is_csv=None): try: response = requests.post( self.get_upload_url(service_id), headers={ "Authorization": "Bearer {}".format(self.auth_token), }, json={ "document": file_contents, "is_csv": is_csv or False, }, timeout=30, ) response.raise_for_status() except requests.RequestException as e: # if doc dl responds with a non-400, (eg 403) it's referring to credentials that the API and Doc DL use. # we don't want to tell users about that, so anything that isn't a 400 (virus scan failed or file type # unrecognised) should be raised as a 500 internal server error here. if e.response is None: raise Exception(f"Unhandled document download error: {repr(e)}") elif e.response.status_code == 400: error = DocumentDownloadError.from_exception(e) current_app.logger.info( "Document download request failed with error: {}".format( error.message ) ) raise error else: raise Exception(f"Unhandled document download error: {e.response.text}") return response.json()["document"]["url"]