From ab4abf1b9ca5228d530f11a65acff83213210d07 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Tue, 21 Jan 2025 20:46:33 -0800 Subject: [PATCH 1/8] thanks cursor --- gradio/processing_utils.py | 12 ++++++++---- test/test_processing_utils.py | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/gradio/processing_utils.py b/gradio/processing_utils.py index c8e3fabd0ce32..053faba96284e 100644 --- a/gradio/processing_utils.py +++ b/gradio/processing_utils.py @@ -328,15 +328,19 @@ def wrapper(*args: Any, **kwargs: Any) -> Awaitable[T]: async def async_ssrf_protected_download(url: str, cache_dir: str) -> str: temp_dir = Path(cache_dir) / hash_url(url) temp_dir.mkdir(exist_ok=True, parents=True) - filename = client_utils.strip_invalid_filename_characters(Path(url).name) + + # Extract base filename without query parameters + parsed_url = urlparse(url) + base_path = parsed_url.path.rstrip("/") + filename = ( + client_utils.strip_invalid_filename_characters(Path(base_path).name) or "file" + ) + full_temp_file_path = str(abspath(temp_dir / filename)) - if Path(full_temp_file_path).exists(): return full_temp_file_path - parsed_url = urlparse(url) hostname = parsed_url.hostname - response = await sh.get( url, domain_whitelist=PUBLIC_HOSTNAME_WHITELIST, _transport=async_transport ) diff --git a/test/test_processing_utils.py b/test/test_processing_utils.py index 5a6fbef6dc649..78e71c815747e 100644 --- a/test/test_processing_utils.py +++ b/test/test_processing_utils.py @@ -442,3 +442,19 @@ async def test_async_private_request_fail(): await processing_utils.async_ssrf_protected_download( "http://192.168.1.250.nip.io/image.png", tempdir.name ) + + +@pytest.mark.asyncio +async def test_download_with_presigned_url(): + with tempfile.TemporaryDirectory() as temp_dir: + # Test URL with query parameters (simulating a presigned URL) + test_url = "https://example.s3.amazonaws.com/video.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=test" + + try: + downloaded_path = await processing_utils.async_ssrf_protected_download(test_url, temp_dir) + + # Verify the downloaded file has the correct base name without query params + assert os.path.basename(downloaded_path) == "video.mp4" + + except Exception as e: + pytest.fail(f"Download failed with presigned URL: {str(e)}") From 1fc258784cbc260287e9212c56f3eada33f2e537 Mon Sep 17 00:00:00 2001 From: gradio-pr-bot Date: Wed, 22 Jan 2025 04:47:33 +0000 Subject: [PATCH 2/8] add changeset --- .changeset/lemon-hotels-retire.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lemon-hotels-retire.md diff --git a/.changeset/lemon-hotels-retire.md b/.changeset/lemon-hotels-retire.md new file mode 100644 index 0000000000000..5b89b22e4b287 --- /dev/null +++ b/.changeset/lemon-hotels-retire.md @@ -0,0 +1,5 @@ +--- +"gradio": minor +--- + +feat:thanks cursor From 0684f8c49fae77c65190dc92293b4444cad72c14 Mon Sep 17 00:00:00 2001 From: gradio-pr-bot Date: Wed, 22 Jan 2025 04:49:00 +0000 Subject: [PATCH 3/8] add changeset --- .changeset/lemon-hotels-retire.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/lemon-hotels-retire.md b/.changeset/lemon-hotels-retire.md index 5b89b22e4b287..7c8026cbb4f6b 100644 --- a/.changeset/lemon-hotels-retire.md +++ b/.changeset/lemon-hotels-retire.md @@ -1,5 +1,5 @@ --- -"gradio": minor +"gradio": patch --- -feat:thanks cursor +fix:thanks cursor From 777c7cc9057d860accccd9c6c66d4306e7311389 Mon Sep 17 00:00:00 2001 From: gradio-pr-bot Date: Wed, 22 Jan 2025 04:53:40 +0000 Subject: [PATCH 4/8] add changeset --- .changeset/lemon-hotels-retire.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/lemon-hotels-retire.md b/.changeset/lemon-hotels-retire.md index 7c8026cbb4f6b..95263b970895f 100644 --- a/.changeset/lemon-hotels-retire.md +++ b/.changeset/lemon-hotels-retire.md @@ -2,4 +2,4 @@ "gradio": patch --- -fix:thanks cursor +fix:Support presigned URLs with gr.Video, gr.Model3D, and other components From c4daf29680785b4ed8cef15191d58687586178f6 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Tue, 21 Jan 2025 20:54:10 -0800 Subject: [PATCH 5/8] changes --- test/test_processing_utils.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/test/test_processing_utils.py b/test/test_processing_utils.py index 78e71c815747e..5a6fbef6dc649 100644 --- a/test/test_processing_utils.py +++ b/test/test_processing_utils.py @@ -442,19 +442,3 @@ async def test_async_private_request_fail(): await processing_utils.async_ssrf_protected_download( "http://192.168.1.250.nip.io/image.png", tempdir.name ) - - -@pytest.mark.asyncio -async def test_download_with_presigned_url(): - with tempfile.TemporaryDirectory() as temp_dir: - # Test URL with query parameters (simulating a presigned URL) - test_url = "https://example.s3.amazonaws.com/video.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=test" - - try: - downloaded_path = await processing_utils.async_ssrf_protected_download(test_url, temp_dir) - - # Verify the downloaded file has the correct base name without query params - assert os.path.basename(downloaded_path) == "video.mp4" - - except Exception as e: - pytest.fail(f"Download failed with presigned URL: {str(e)}") From 6e6c1f114d752885e619fb65b3ae539080f5cbac Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Tue, 21 Jan 2025 20:54:56 -0800 Subject: [PATCH 6/8] changes --- gradio/processing_utils.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gradio/processing_utils.py b/gradio/processing_utils.py index 053faba96284e..02a8e9ab06965 100644 --- a/gradio/processing_utils.py +++ b/gradio/processing_utils.py @@ -328,14 +328,13 @@ def wrapper(*args: Any, **kwargs: Any) -> Awaitable[T]: async def async_ssrf_protected_download(url: str, cache_dir: str) -> str: temp_dir = Path(cache_dir) / hash_url(url) temp_dir.mkdir(exist_ok=True, parents=True) - - # Extract base filename without query parameters + parsed_url = urlparse(url) base_path = parsed_url.path.rstrip("/") filename = ( client_utils.strip_invalid_filename_characters(Path(base_path).name) or "file" ) - + full_temp_file_path = str(abspath(temp_dir / filename)) if Path(full_temp_file_path).exists(): return full_temp_file_path From 0f1c5996a419f7325b2f4b8c0677fb2b789bf724 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Tue, 21 Jan 2025 21:16:50 -0800 Subject: [PATCH 7/8] video --- test/components/test_video.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/components/test_video.py b/test/components/test_video.py index 072aac6c3d590..e0c32cb705f2f 100644 --- a/test/components/test_video.py +++ b/test/components/test_video.py @@ -99,10 +99,17 @@ async def test_component_functions(self): output_with_subtitles = output_with_subtitles.model_dump() assert output_with_subtitles["subtitles"]["path"].endswith(".vtt") + video = gr.Video(format="wav") + video_url_with_query_param = "https://github.com/gradio-app/gradio/raw/refs/heads/main/test/test_files/playable_but_bad_container.mp4?query=fake" + postprocessed_video_with_query_param = video.postprocess(video_url_with_query_param) + assert postprocessed_video_with_query_param + assert postprocessed_video_with_query_param.model_dump()["video"]["path"].endswith("playable_but_bad_container.wav") + p_video = gr.Video() video_with_subtitle = gr.Video() postprocessed_video = p_video.postprocess(Path(y_vid_path)) assert postprocessed_video + postprocessed_video = postprocessed_video.model_dump() postprocessed_video_with_subtitle = video_with_subtitle.postprocess( (Path(y_vid_path), Path(subtitles_path)) From 42c7a6437d4a333fae9b4ff94afd874e3e087e57 Mon Sep 17 00:00:00 2001 From: Abubakar Abid Date: Tue, 21 Jan 2025 21:17:13 -0800 Subject: [PATCH 8/8] changes --- test/components/test_video.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/components/test_video.py b/test/components/test_video.py index e0c32cb705f2f..cc56fd7247519 100644 --- a/test/components/test_video.py +++ b/test/components/test_video.py @@ -101,9 +101,13 @@ async def test_component_functions(self): video = gr.Video(format="wav") video_url_with_query_param = "https://github.com/gradio-app/gradio/raw/refs/heads/main/test/test_files/playable_but_bad_container.mp4?query=fake" - postprocessed_video_with_query_param = video.postprocess(video_url_with_query_param) + postprocessed_video_with_query_param = video.postprocess( + video_url_with_query_param + ) assert postprocessed_video_with_query_param - assert postprocessed_video_with_query_param.model_dump()["video"]["path"].endswith("playable_but_bad_container.wav") + assert postprocessed_video_with_query_param.model_dump()["video"][ + "path" + ].endswith("playable_but_bad_container.wav") p_video = gr.Video() video_with_subtitle = gr.Video()