master
jinql 2025-09-06 14:59:02 +08:00
parent 5972366cae
commit a92dd232ee
2 changed files with 32 additions and 42 deletions

View File

@ -33,7 +33,7 @@ async def get_favicon(
bg_tasks: BackgroundTasks,
url: Optional[str] = Query(None, description="网址eg. https://www.baidu.com"),
refresh: Optional[str] = Query(None, include_in_schema=False),
sync: Optional[str] = Query('true', description="是否使用同步方式获取")
sync: Optional[str] = Query('false', description="是否使用同步方式获取")
):
"""获取网站图标"""
return await _service.get_favicon_handler(request, bg_tasks, url, refresh, sync)

View File

@ -37,9 +37,6 @@ class FaviconService:
"""图标服务类,封装所有与图标获取、缓存和处理相关的功能"""
def __init__(self):
# 使用锁保证线程安全
self._lock = Lock()
# 全局计数器和集合
self.url_count = 0
self.request_icon_count = 0
@ -274,7 +271,6 @@ class FaviconService:
icon_content = None
try:
with self._lock:
if entity.domain in self.domain_list:
self._queue_pull(True, self.total_queue)
return _cached or default_icon_content
@ -333,7 +329,6 @@ class FaviconService:
except Exception as e:
logger.error(f"写入缓存文件失败: {e}")
with self._lock:
self.request_icon_count += 1
return icon_content
@ -341,7 +336,6 @@ class FaviconService:
logger.error(f"获取图标时发生错误 {entity.domain}: {e}")
return _cached or default_icon_content
finally:
with self._lock:
if entity.domain in self.domain_list:
self.domain_list.remove(entity.domain)
# 任务完成,从两个队列中移出元素
@ -350,7 +344,6 @@ class FaviconService:
def get_count(self) -> Dict[str, int]:
"""获取统计数据"""
with self._lock:
return {
'url_count': self.url_count,
'request_icon_count': self.request_icon_count,
@ -369,9 +362,8 @@ class FaviconService:
) -> dict[str, str] | Response:
"""处理获取图标的请求"""
logger.info(f"队列大小:{self.icon_queue.qsize()} | {self.total_queue.qsize()}")
logger.info(f"队列大小:{self.icon_queue.qsize()} | {self.total_queue.qsize()} | {len(favicon.failed_urls)}")
with self._lock:
self.url_count += 1
# 验证URL参数
@ -387,7 +379,6 @@ class FaviconService:
return self.get_default(self.time_of_7_days)
# 检查内存缓存中的失败URL
with self._lock:
if entity.domain in favicon.failed_urls:
_expire_time = favicon.failed_urls[entity.domain]
if int(time.time()) <= _expire_time:
@ -401,12 +392,11 @@ class FaviconService:
if cached_icon:
# 使用缓存图标
icon_content = cached_icon
with self._lock:
self.request_cache_count += 1
# 确定内容类型和缓存时间
content_type = filetype.guess_mime(icon_content) if icon_content else ""
cache_time = self.time_of_1_hours * random.randint(1, 6) if self._is_default_icon_byte(icon_content) else self.time_of_7_days
cache_time = self.time_of_12_hours if self._is_default_icon_byte(icon_content) else self.time_of_7_days
# 乐观缓存机制:检查缓存是否已过期但仍有缓存内容
# _cached 存在但 cached_icon 为 None 表示缓存已过期
@ -422,10 +412,10 @@ class FaviconService:
media_type=content_type if content_type else "image/x-icon",
headers=self._get_header(content_type, cache_time))
else:
_referrer = request.headers.get('referrer') or request.headers.get('referer')
# 检查sync参数
is_sync = sync in ['true', '1', 'True']
if not is_sync:
if (not is_sync) or (_referrer and not _referrer.startswith('https://api.xinac.net')):
# 返回默认图片并加入后台队列
logger.info(f"返回默认图片并加入后台队列: {entity.domain}")
# 开始图标处理,加入两个队列
@ -458,7 +448,7 @@ class FaviconService:
# 确定内容类型和缓存时间
content_type = filetype.guess_mime(icon_content) if icon_content else ""
cache_time = self.time_of_1_hours * random.randint(1, 6) if self._is_default_icon_byte(icon_content) else self.time_of_7_days
cache_time = self.time_of_12_hours if self._is_default_icon_byte(icon_content) else self.time_of_7_days
return Response(content=icon_content,
media_type=content_type if content_type else "image/x-icon",