diff --git a/ayon_api/_api_helpers/bundles_addons.py b/ayon_api/_api_helpers/bundles_addons.py index 6355b62eb..9fc5de162 100644 --- a/ayon_api/_api_helpers/bundles_addons.py +++ b/ayon_api/_api_helpers/bundles_addons.py @@ -398,7 +398,7 @@ def upload_addon_zip( """ response = self.upload_file( - "addons/install", + "api/addons/install", src_filepath, progress=progress, request_type=RequestTypes.post, @@ -448,9 +448,11 @@ def download_addon_private_file( "private", filename ) - url = f"{self.get_base_url()}/{endpoint}" self.download_file( - url, dst_filepath, chunk_size=chunk_size, progress=progress + endpoint, + dst_filepath, + chunk_size=chunk_size, + progress=progress, ) return dst_filepath diff --git a/ayon_api/_api_helpers/dependency_packages.py b/ayon_api/_api_helpers/dependency_packages.py index dc1f43e94..a2c72f40a 100644 --- a/ayon_api/_api_helpers/dependency_packages.py +++ b/ayon_api/_api_helpers/dependency_packages.py @@ -189,7 +189,7 @@ def download_dependency_package( route = self._get_dependency_package_route(src_filename) package_filepath = os.path.join(dst_directory, dst_filename) self.download_file( - route, + f"api/{route}", package_filepath, chunk_size=chunk_size, progress=progress @@ -225,7 +225,7 @@ def upload_dependency_package( ) route = self._get_dependency_package_route(dst_filename) - self.upload_file(route, src_filepath, progress=progress) + self.upload_file(f"api/{route}", src_filepath, progress=progress) def _get_dependency_package_route( self, filename: Optional[str] = None diff --git a/ayon_api/_api_helpers/installers.py b/ayon_api/_api_helpers/installers.py index be2bcaaec..72aa5193c 100644 --- a/ayon_api/_api_helpers/installers.py +++ b/ayon_api/_api_helpers/installers.py @@ -143,7 +143,7 @@ def download_installer( """ return self.download_file( - f"desktop/installers/{filename}", + f"api/desktop/installers/{filename}", dst_filepath, chunk_size=chunk_size, progress=progress @@ -168,7 +168,7 @@ def upload_installer( """ return self.upload_file( - f"desktop/installers/{dst_filename}", + f"api/desktop/installers/{dst_filename}", src_filepath, progress=progress ) diff --git a/ayon_api/_api_helpers/thumbnails.py b/ayon_api/_api_helpers/thumbnails.py index 577536e28..9d534fd5e 100644 --- a/ayon_api/_api_helpers/thumbnails.py +++ b/ayon_api/_api_helpers/thumbnails.py @@ -256,7 +256,7 @@ def create_thumbnail( mime_type = get_media_mime_type(src_filepath) response = self.upload_file( - f"projects/{project_name}/thumbnails", + f"api/projects/{project_name}/thumbnails", src_filepath, request_type=RequestTypes.post, headers={"Content-Type": mime_type}, @@ -295,7 +295,7 @@ def create_thumbnail_with_stream( mime_type = get_media_mime_type_for_stream(stream) response = self.upload_file_from_stream( - f"projects/{project_name}/thumbnails", + f"api/projects/{project_name}/thumbnails", stream, request_type=RequestTypes.post, headers={"Content-Type": mime_type}, @@ -325,7 +325,7 @@ def update_thumbnail( mime_type = get_media_mime_type(src_filepath) response = self.upload_file( - f"projects/{project_name}/thumbnails/{thumbnail_id}", + f"api/projects/{project_name}/thumbnails/{thumbnail_id}", src_filepath, request_type=RequestTypes.put, headers={"Content-Type": mime_type}, @@ -351,7 +351,7 @@ def update_thumbnail_from_stream( """ mime_type = get_media_mime_type_for_stream(stream) response = self.upload_file_from_stream( - f"projects/{project_name}/thumbnails/{thumbnail_id}", + f"api/projects/{project_name}/thumbnails/{thumbnail_id}", stream, request_type=RequestTypes.put, headers={"Content-Type": mime_type}, diff --git a/ayon_api/server_api.py b/ayon_api/server_api.py index 4dc4b3449..6705126b2 100644 --- a/ayon_api/server_api.py +++ b/ayon_api/server_api.py @@ -1352,7 +1352,7 @@ def _endpoint_to_url( def _download_file_to_stream( self, - url: str, + endpoint: str, stream: StreamType, chunk_size: int, progress: TransferProgress, @@ -1367,7 +1367,11 @@ def _download_file_to_stream( else: get_func = self._session_functions_mapping[RequestTypes.get] + url = self._endpoint_to_url(endpoint, use_rest=False) + progress.set_source_url(url) + retries = self.get_default_max_retries() + api_prepended = False for attempt in range(retries): # Continue in download offset = progress.get_transferred_size() @@ -1376,6 +1380,18 @@ def _download_file_to_stream( try: with get_func(url, **kwargs) as response: + # Auto-fix missing 'api/' + if response.status_code == 405 and not api_prepended: + api_prepended = True + if ( + not endpoint.startswith(self._base_url) + and not endpoint.startswith("api/") + ): + url = self._endpoint_to_url( + endpoint, use_rest=True + ) + progress.set_destination_url(url) + continue response.raise_for_status() if progress.get_content_size() is None: progress.set_content_size( @@ -1395,6 +1411,12 @@ def _download_file_to_stream( raise progress.next_attempt() + if api_prepended: + self.log.warning( + f"Auto-fixed endpoint '{endpoint}' -> 'api/{endpoint}'." + " Please fix the endpoit passed to the function." + ) + def download_file_to_stream( self, endpoint: str, @@ -1427,17 +1449,14 @@ def download_file_to_stream( if not chunk_size: chunk_size = self.default_download_chunk_size - url = self._endpoint_to_url(endpoint, use_rest=False) - if progress is None: progress = TransferProgress() - progress.set_source_url(url) progress.set_started() try: self._download_file_to_stream( - url, stream, chunk_size, progress + endpoint, stream, chunk_size, progress ) except Exception as exc: @@ -1585,13 +1604,7 @@ def _upload_chunks_iter( bytes: Chunk of file. """ - # Get size of file - file_stream.seek(0, io.SEEK_END) - size = file_stream.tell() file_stream.seek(0) - # Set content size to progress object - progress.set_content_size(size) - while True: chunk = file_stream.read(chunk_size) if not chunk: @@ -1601,7 +1614,7 @@ def _upload_chunks_iter( def _upload_file( self, - url: str, + endpoint: str, stream: StreamType, progress: TransferProgress, request_type: Optional[RequestType] = None, @@ -1611,7 +1624,7 @@ def _upload_file( """Upload file to server. Args: - url (str): Url where file will be uploaded. + endpoint (str): Endpoint used to upload. stream (StreamType): File stream. progress (TransferProgress): Object that gives ability to track progress. @@ -1629,6 +1642,10 @@ def _upload_file( if request_type is None: request_type = RequestTypes.put + endpoint = endpoint.lstrip("/") + url = self._endpoint_to_url(endpoint, use_rest=False) + progress.set_destination_url(url) + if self._session is None: headers = kwargs.setdefault("headers", {}) for key, value in self.get_headers().items(): @@ -1643,6 +1660,14 @@ def _upload_file( retries = self.get_default_max_retries() response = None + + # Get size of file + stream.seek(0, io.SEEK_END) + size = stream.tell() + # Set content size to progress object + progress.set_content_size(size) + + api_prepended = False for attempt in range(retries): try: response = post_func( @@ -1652,6 +1677,16 @@ def _upload_file( ), **kwargs ) + # Auto-fix missing 'api/' + if response.status_code == 405 and not api_prepended: + api_prepended = True + if ( + not endpoint.startswith(self._base_url) + and not endpoint.startswith("api/") + ): + url = self._endpoint_to_url(endpoint, use_rest=True) + progress.set_destination_url(url) + continue break except ( @@ -1664,6 +1699,11 @@ def _upload_file( progress.reset_transferred() response.raise_for_status() + if api_prepended: + self.log.warning( + f"Auto-fixed endpoint '{endpoint}' -> 'api/{endpoint}'." + " Please fix the endpoit passed to the function." + ) return response def upload_file_from_stream( @@ -1694,19 +1734,20 @@ def upload_file_from_stream( requests.Response: Response object """ - url = self._endpoint_to_url(endpoint) - # Create dummy object so the function does not have to check # 'progress' variable everywhere if progress is None: progress = TransferProgress() - progress.set_destination_url(url) progress.set_started() try: return self._upload_file( - url, stream, progress, request_type, **kwargs + endpoint, + stream, + progress, + request_type, + **kwargs ) except Exception as exc: @@ -1751,7 +1792,11 @@ def upload_file( with open(filepath, "rb") as stream: return self.upload_file_from_stream( - endpoint, stream, progress, request_type, **kwargs + endpoint, + stream, + progress, + request_type, + **kwargs ) def upload_reviewable( @@ -1813,7 +1858,7 @@ def upload_reviewable( query = prepare_query_string({"label": label or None}) endpoint = ( - f"/projects/{project_name}" + f"api/projects/{project_name}" f"/versions/{version_id}/reviewables{query}" ) return self.upload_file(