diff --git a/api/core/tools/signature.py b/api/core/tools/signature.py index e8281fd9d4..8f00dde259 100644 --- a/api/core/tools/signature.py +++ b/api/core/tools/signature.py @@ -28,9 +28,12 @@ def sign_tool_file(tool_file_id: str, extension: str, for_external: bool = True) def sign_upload_file(upload_file_id: str, extension: str, for_external: bool = True) -> str: """ - sign file to get a temporary url for plugin access + Sign an upload file to get a temporary image preview URL. + + External URLs are the default because uploaded-file previews are returned to + user-facing retrieval responses. Internal URLs remain available for callers + that need to access files inside the deployment network. """ - # Use internal URL for plugin/tool file access in Docker environments base_url = dify_config.FILES_URL if for_external else (dify_config.INTERNAL_FILES_URL or dify_config.FILES_URL) file_preview_url = f"{base_url}/files/{upload_file_id}/image-preview" diff --git a/api/tests/unit_tests/core/tools/test_signature.py b/api/tests/unit_tests/core/tools/test_signature.py index 353988d7a6..7f76bdf541 100644 --- a/api/tests/unit_tests/core/tools/test_signature.py +++ b/api/tests/unit_tests/core/tools/test_signature.py @@ -89,7 +89,7 @@ def test_verify_tool_file_signature_rejects_expired_signature(monkeypatch: pytes assert verify_tool_file_signature("tool-file-id", timestamp, nonce, sign) is False -def test_sign_upload_file_prefers_internal_url(monkeypatch: pytest.MonkeyPatch) -> None: +def test_sign_upload_file_for_external_uses_files_url(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr("core.tools.signature.time.time", lambda: 1700000000) monkeypatch.setattr("core.tools.signature.os.urandom", lambda _: b"\x03" * 16) monkeypatch.setattr("core.tools.signature.dify_config.SECRET_KEY", "unit-secret") @@ -100,6 +100,24 @@ def test_sign_upload_file_prefers_internal_url(monkeypatch: pytest.MonkeyPatch) parsed = urlparse(url) query = parse_qs(parsed.query) + assert parsed.netloc == "files.example.com" + assert parsed.path == "/files/upload-id/image-preview" + assert query["timestamp"][0] + assert query["nonce"][0] + assert query["sign"][0] + + +def test_sign_upload_file_for_internal_prefers_internal_url(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr("core.tools.signature.time.time", lambda: 1700000000) + monkeypatch.setattr("core.tools.signature.os.urandom", lambda _: b"\x08" * 16) + monkeypatch.setattr("core.tools.signature.dify_config.SECRET_KEY", "unit-secret") + monkeypatch.setattr("core.tools.signature.dify_config.FILES_URL", "https://files.example.com") + monkeypatch.setattr("core.tools.signature.dify_config.INTERNAL_FILES_URL", "https://internal.example.com") + + url = sign_upload_file("upload-id", ".png", for_external=False) + parsed = urlparse(url) + query = parse_qs(parsed.query) + assert parsed.netloc == "internal.example.com" assert parsed.path == "/files/upload-id/image-preview" assert query["timestamp"][0]