Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ TENCENT_COS_SECRET_KEY=your-secret-key
TENCENT_COS_SECRET_ID=your-secret-id
TENCENT_COS_REGION=your-region
TENCENT_COS_SCHEME=your-scheme
TENCENT_COS_CUSTOM_DOMAIN=your-custom-domain

# Huawei OBS Storage Configuration
HUAWEI_OBS_BUCKET_NAME=your-bucket-name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ class TencentCloudCOSStorageConfig(BaseSettings):
description="Protocol scheme for COS requests: 'https' (recommended) or 'http'",
default=None,
)

TENCENT_COS_CUSTOM_DOMAIN: str | None = Field(
description="Tencent Cloud COS custom domain setting",
default=None,
)
20 changes: 14 additions & 6 deletions api/extensions/storage/tencent_cos_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@ def __init__(self):
super().__init__()

self.bucket_name = dify_config.TENCENT_COS_BUCKET_NAME
config = CosConfig(
Region=dify_config.TENCENT_COS_REGION,
SecretId=dify_config.TENCENT_COS_SECRET_ID,
SecretKey=dify_config.TENCENT_COS_SECRET_KEY,
Scheme=dify_config.TENCENT_COS_SCHEME,
)
if dify_config.TENCENT_COS_CUSTOM_DOMAIN:
config = CosConfig(
Domain=dify_config.TENCENT_COS_CUSTOM_DOMAIN,
SecretId=dify_config.TENCENT_COS_SECRET_ID,
SecretKey=dify_config.TENCENT_COS_SECRET_KEY,
Scheme=dify_config.TENCENT_COS_SCHEME,
)
else:
config = CosConfig(
Region=dify_config.TENCENT_COS_REGION,
SecretId=dify_config.TENCENT_COS_SECRET_ID,
SecretKey=dify_config.TENCENT_COS_SECRET_KEY,
Scheme=dify_config.TENCENT_COS_SCHEME,
)
self.client = CosS3Client(config)

def save(self, filename, data):
Expand Down
71 changes: 70 additions & 1 deletion api/tests/unit_tests/oss/tencent_cos/test_tencent_cos.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from unittest.mock import patch
from unittest.mock import MagicMock, patch

import pytest
from qcloud_cos import CosConfig
Expand All @@ -18,3 +18,72 @@ def setup_method(self, setup_tencent_cos_mock):
with patch.object(CosConfig, "__init__", return_value=None):
self.storage = TencentCosStorage()
self.storage.bucket_name = get_example_bucket()


class TestTencentCosConfiguration:
"""Tests for TencentCosStorage initialization with different configurations."""

def test_init_with_custom_domain(self):
"""Test initialization with custom domain configured."""
# Mock dify_config to return custom domain configuration
mock_dify_config = MagicMock()
mock_dify_config.TENCENT_COS_CUSTOM_DOMAIN = "cos.example.com"
mock_dify_config.TENCENT_COS_SECRET_ID = "test-secret-id"
mock_dify_config.TENCENT_COS_SECRET_KEY = "test-secret-key"
mock_dify_config.TENCENT_COS_SCHEME = "https"

# Mock CosConfig and CosS3Client
mock_config_instance = MagicMock()
mock_client = MagicMock()

with (
patch("extensions.storage.tencent_cos_storage.dify_config", mock_dify_config),
patch(
"extensions.storage.tencent_cos_storage.CosConfig", return_value=mock_config_instance
) as mock_cos_config,
patch("extensions.storage.tencent_cos_storage.CosS3Client", return_value=mock_client),
):
TencentCosStorage()

# Verify CosConfig was called with Domain parameter (not Region)
mock_cos_config.assert_called_once()
call_kwargs = mock_cos_config.call_args[1]
assert "Domain" in call_kwargs
assert call_kwargs["Domain"] == "cos.example.com"
assert "Region" not in call_kwargs
assert call_kwargs["SecretId"] == "test-secret-id"
assert call_kwargs["SecretKey"] == "test-secret-key"
assert call_kwargs["Scheme"] == "https"

def test_init_with_region(self):
"""Test initialization with region configured (no custom domain)."""
# Mock dify_config to return region configuration
mock_dify_config = MagicMock()
mock_dify_config.TENCENT_COS_CUSTOM_DOMAIN = None
mock_dify_config.TENCENT_COS_REGION = "ap-guangzhou"
mock_dify_config.TENCENT_COS_SECRET_ID = "test-secret-id"
mock_dify_config.TENCENT_COS_SECRET_KEY = "test-secret-key"
mock_dify_config.TENCENT_COS_SCHEME = "https"

# Mock CosConfig and CosS3Client
mock_config_instance = MagicMock()
mock_client = MagicMock()

with (
patch("extensions.storage.tencent_cos_storage.dify_config", mock_dify_config),
patch(
"extensions.storage.tencent_cos_storage.CosConfig", return_value=mock_config_instance
) as mock_cos_config,
patch("extensions.storage.tencent_cos_storage.CosS3Client", return_value=mock_client),
):
TencentCosStorage()

# Verify CosConfig was called with Region parameter (not Domain)
mock_cos_config.assert_called_once()
call_kwargs = mock_cos_config.call_args[1]
assert "Region" in call_kwargs
assert call_kwargs["Region"] == "ap-guangzhou"
assert "Domain" not in call_kwargs
assert call_kwargs["SecretId"] == "test-secret-id"
assert call_kwargs["SecretKey"] == "test-secret-key"
assert call_kwargs["Scheme"] == "https"
1 change: 1 addition & 0 deletions docker/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ TENCENT_COS_SECRET_KEY=your-secret-key
TENCENT_COS_SECRET_ID=your-secret-id
TENCENT_COS_REGION=your-region
TENCENT_COS_SCHEME=your-scheme
TENCENT_COS_CUSTOM_DOMAIN=your-custom-domain

# Oracle Storage Configuration
#
Expand Down
1 change: 1 addition & 0 deletions docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ x-shared-env: &shared-api-worker-env
TENCENT_COS_SECRET_ID: ${TENCENT_COS_SECRET_ID:-your-secret-id}
TENCENT_COS_REGION: ${TENCENT_COS_REGION:-your-region}
TENCENT_COS_SCHEME: ${TENCENT_COS_SCHEME:-your-scheme}
TENCENT_COS_CUSTOM_DOMAIN: ${TENCENT_COS_CUSTOM_DOMAIN:-your-custom-domain}
OCI_ENDPOINT: ${OCI_ENDPOINT:-https://your-object-storage-namespace.compat.objectstorage.us-ashburn-1.oraclecloud.com}
OCI_BUCKET_NAME: ${OCI_BUCKET_NAME:-your-bucket-name}
OCI_ACCESS_KEY: ${OCI_ACCESS_KEY:-your-access-key}
Expand Down
Loading