This commit is contained in:
FFXN 2026-05-09 02:58:26 +00:00 committed by GitHub
commit 01f91f2063
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 76 additions and 8 deletions

View File

@ -115,7 +115,7 @@ class PdfExtractor(BaseExtractor):
"""
image_content = []
upload_files = []
base_url = dify_config.INTERNAL_FILES_URL or dify_config.FILES_URL
base_url = dify_config.FILES_URL
try:
image_objects = page.get_objects(filter=(pdfium_c.FPDF_PAGEOBJ_IMAGE,))

View File

@ -110,7 +110,7 @@ class WordExtractor(BaseExtractor):
def _extract_images_from_docx(self, doc):
image_count = 0
image_map = {}
base_url = dify_config.INTERNAL_FILES_URL or dify_config.FILES_URL
base_url = dify_config.FILES_URL
for r_id, rel in doc.part.rels.items():
if "image" in rel.target_ref:

View File

@ -26,12 +26,15 @@ def sign_tool_file(tool_file_id: str, extension: str, for_external: bool = True)
return f"{file_preview_url}?timestamp={timestamp}&nonce={nonce}&sign={encoded_sign}"
def sign_upload_file(upload_file_id: str, extension: str) -> str:
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.INTERNAL_FILES_URL or dify_config.FILES_URL
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"
timestamp = str(int(time.time()))

View File

@ -1020,7 +1020,7 @@ class DocumentSegment(Base):
encoded_sign = base64.urlsafe_b64encode(sign).decode()
params = f"timestamp={timestamp}&nonce={nonce}&sign={encoded_sign}"
reference_url = dify_config.CONSOLE_API_URL or ""
reference_url = dify_config.FILES_URL or dify_config.CONSOLE_API_URL or ""
base_url = f"{reference_url}/files/{upload_file_id}/image-preview"
source_url = f"{base_url}?{params}"
attachment_list.append(

View File

@ -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]

View File

@ -12,7 +12,9 @@ This test suite covers:
import json
import pickle
from datetime import UTC, datetime
from types import SimpleNamespace
from unittest.mock import Mock, patch
from urllib.parse import parse_qs, urlparse
from uuid import uuid4
from core.rag.index_processor.constant.index_type import IndexTechniqueType
@ -676,6 +678,51 @@ class TestDocumentSegmentIndexing:
# Assert
assert segment.hit_count == 5
def test_document_segment_attachments_prefers_files_url_for_source_url(self, monkeypatch):
"""Test attachment source URLs use FILES_URL before falling back to CONSOLE_API_URL."""
# Arrange
segment = DocumentSegment(
tenant_id="tenant-1",
dataset_id="dataset-1",
document_id="document-1",
position=1,
content="Test",
word_count=1,
tokens=2,
created_by="user-1",
)
segment.id = "segment-1"
attachment = SimpleNamespace(
id="upload-1",
name="image.png",
size=128,
extension="png",
mime_type="image/png",
)
monkeypatch.setattr("models.dataset.time.time", lambda: 1700000000)
monkeypatch.setattr("models.dataset.os.urandom", lambda _: b"\x01" * 16)
monkeypatch.setattr("models.dataset.dify_config.SECRET_KEY", "unit-secret")
monkeypatch.setattr("models.dataset.dify_config.FILES_URL", "https://files.example.com")
monkeypatch.setattr("models.dataset.dify_config.CONSOLE_API_URL", "https://console.example.com")
with patch("models.dataset.db") as mock_db:
mock_db.session.execute.return_value.all.return_value = [(Mock(), attachment)]
# Act
attachments = segment.attachments
# Assert
assert len(attachments) == 1
source_url = attachments[0]["source_url"]
parsed = urlparse(source_url)
query = parse_qs(parsed.query)
assert parsed.netloc == "files.example.com"
assert parsed.path == "/files/upload-1/image-preview"
assert query["timestamp"] == ["1700000000"]
assert query["nonce"] == ["01010101010101010101010101010101"]
assert query["sign"][0]
def test_document_segment_error_tracking(self):
"""Test document segment error tracking."""
# Arrange