Add File
This commit is contained in:
148
src/landppt/services/url_service.py
Normal file
148
src/landppt/services/url_service.py
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
"""
|
||||||
|
URL生成服务
|
||||||
|
统一管理所有URL生成逻辑,支持反向代理域名配置
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Optional
|
||||||
|
from urllib.parse import urljoin
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class URLService:
|
||||||
|
"""URL生成服务"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._base_url = None
|
||||||
|
self._config_service = None
|
||||||
|
|
||||||
|
def _get_config_service(self):
|
||||||
|
"""延迟加载配置服务,避免循环导入"""
|
||||||
|
if self._config_service is None:
|
||||||
|
from .config_service import config_service
|
||||||
|
self._config_service = config_service
|
||||||
|
return self._config_service
|
||||||
|
|
||||||
|
def _get_base_url(self) -> str:
|
||||||
|
"""获取基础URL配置"""
|
||||||
|
# 每次都重新获取配置,确保使用最新的配置
|
||||||
|
try:
|
||||||
|
config_service = self._get_config_service()
|
||||||
|
app_config = config_service.get_config_by_category('app_config')
|
||||||
|
base_url = app_config.get('base_url', 'http://localhost:8000')
|
||||||
|
|
||||||
|
# 确保URL不以斜杠结尾
|
||||||
|
if base_url.endswith('/'):
|
||||||
|
base_url = base_url[:-1]
|
||||||
|
|
||||||
|
logger.debug(f"Using base URL: {base_url}")
|
||||||
|
return base_url
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"无法获取基础URL配置,使用默认值: {e}")
|
||||||
|
return 'http://localhost:8000'
|
||||||
|
|
||||||
|
def build_absolute_url(self, relative_path: str) -> str:
|
||||||
|
"""构建绝对URL"""
|
||||||
|
base_url = self._get_base_url()
|
||||||
|
|
||||||
|
# 确保相对路径以斜杠开头
|
||||||
|
if not relative_path.startswith('/'):
|
||||||
|
relative_path = '/' + relative_path
|
||||||
|
|
||||||
|
absolute_url = f"{base_url}{relative_path}"
|
||||||
|
logger.debug(f"Built absolute URL: {relative_path} -> {absolute_url}")
|
||||||
|
return absolute_url
|
||||||
|
|
||||||
|
def build_image_url(self, image_id: str) -> str:
|
||||||
|
"""构建图片访问URL"""
|
||||||
|
return self.build_absolute_url(f"/api/image/view/{image_id}")
|
||||||
|
|
||||||
|
def build_image_thumbnail_url(self, image_id: str) -> str:
|
||||||
|
"""构建图片缩略图URL"""
|
||||||
|
return self.build_absolute_url(f"/api/image/thumbnail/{image_id}")
|
||||||
|
|
||||||
|
def build_image_download_url(self, image_id: str) -> str:
|
||||||
|
"""构建图片下载URL"""
|
||||||
|
return self.build_absolute_url(f"/api/image/download/{image_id}")
|
||||||
|
|
||||||
|
def build_static_url(self, static_path: str) -> str:
|
||||||
|
"""构建静态资源URL"""
|
||||||
|
# 确保静态路径不以斜杠开头(因为/static已经包含了)
|
||||||
|
if static_path.startswith('/'):
|
||||||
|
static_path = static_path[1:]
|
||||||
|
return self.build_absolute_url(f"/static/{static_path}")
|
||||||
|
|
||||||
|
def build_temp_url(self, temp_path: str) -> str:
|
||||||
|
"""构建临时文件URL"""
|
||||||
|
# 确保临时路径不以斜杠开头(因为/temp已经包含了)
|
||||||
|
if temp_path.startswith('/'):
|
||||||
|
temp_path = temp_path[1:]
|
||||||
|
return self.build_absolute_url(f"/temp/{temp_path}")
|
||||||
|
|
||||||
|
def get_current_base_url(self) -> str:
|
||||||
|
"""获取当前配置的基础URL"""
|
||||||
|
return self._get_base_url()
|
||||||
|
|
||||||
|
def is_localhost_url(self, url: str) -> bool:
|
||||||
|
"""检查URL是否为localhost"""
|
||||||
|
return 'localhost' in url or '127.0.0.1' in url
|
||||||
|
|
||||||
|
def validate_base_url(self, base_url: str) -> bool:
|
||||||
|
"""验证基础URL格式"""
|
||||||
|
try:
|
||||||
|
if not base_url:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 基本格式检查
|
||||||
|
if not (base_url.startswith('http://') or base_url.startswith('https://')):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 不能以斜杠结尾
|
||||||
|
if base_url.endswith('/'):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"URL validation error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# 全局URL服务实例
|
||||||
|
_url_service = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_url_service() -> URLService:
|
||||||
|
"""获取全局URL服务实例"""
|
||||||
|
global _url_service
|
||||||
|
if _url_service is None:
|
||||||
|
_url_service = URLService()
|
||||||
|
return _url_service
|
||||||
|
|
||||||
|
|
||||||
|
# 便捷函数
|
||||||
|
def build_absolute_url(relative_path: str) -> str:
|
||||||
|
"""构建绝对URL的便捷函数"""
|
||||||
|
return get_url_service().build_absolute_url(relative_path)
|
||||||
|
|
||||||
|
|
||||||
|
def build_image_url(image_id: str) -> str:
|
||||||
|
"""构建图片URL的便捷函数"""
|
||||||
|
return get_url_service().build_image_url(image_id)
|
||||||
|
|
||||||
|
|
||||||
|
def build_image_thumbnail_url(image_id: str) -> str:
|
||||||
|
"""构建图片缩略图URL的便捷函数"""
|
||||||
|
return get_url_service().build_image_thumbnail_url(image_id)
|
||||||
|
|
||||||
|
|
||||||
|
def build_image_download_url(image_id: str) -> str:
|
||||||
|
"""构建图片下载URL的便捷函数"""
|
||||||
|
return get_url_service().build_image_download_url(image_id)
|
||||||
|
|
||||||
|
|
||||||
|
def get_current_base_url() -> str:
|
||||||
|
"""获取当前基础URL的便捷函数"""
|
||||||
|
return get_url_service().get_current_base_url()
|
||||||
Reference in New Issue
Block a user