You've already forked favicon-api-async
25.09.10
This commit is contained in:
@@ -16,8 +16,8 @@ from fastapi import Request, BackgroundTasks
|
||||
from fastapi.responses import Response
|
||||
|
||||
import setting
|
||||
from favicon_app.models import Favicon
|
||||
from favicon_app.utils import header, redis_pool
|
||||
from favicon_app.models import Favicon, favicon
|
||||
from favicon_app.utils import header
|
||||
from favicon_app.utils.file_util import FileUtil
|
||||
from favicon_app.utils.filetype import helpers, filetype
|
||||
|
||||
@@ -36,11 +36,6 @@ async def get_favicon_handler(request: Request,
|
||||
refresh: Optional[str] = None) -> dict[str, str] | Response:
|
||||
"""异步处理获取图标的请求"""
|
||||
|
||||
logger.info(
|
||||
f"队列大小(异步) queue/failed:"
|
||||
f"{await redis_pool.get_cache_size(prefix=redis_pool.ICON_QUEUE_PREFIX)} "
|
||||
f"| {await redis_pool.get_cache_size(prefix=redis_pool.FAILED_DOMAINS_PREFIX)}")
|
||||
|
||||
# 验证URL参数
|
||||
if not url:
|
||||
return {"message": "请提供url参数"}
|
||||
@@ -48,14 +43,19 @@ async def get_favicon_handler(request: Request,
|
||||
try:
|
||||
entity = Favicon(url)
|
||||
|
||||
logger.info(f"-> failed url size: {len(favicon.failed_urls)}")
|
||||
|
||||
# 验证域名
|
||||
if not entity.domain:
|
||||
logger.warning(f"无效的URL: {url}")
|
||||
return get_default(setting.time_of_7_days)
|
||||
return get_default(setting.time_of_1_days)
|
||||
|
||||
# 检查缓存中的失败URL
|
||||
if await redis_pool.is_domain_failed(entity.domain):
|
||||
return get_default(setting.time_of_1_days)
|
||||
if entity.domain in favicon.failed_urls:
|
||||
if int(time.time()) <= favicon.failed_urls.get(entity.domain):
|
||||
return get_default(setting.time_of_1_days)
|
||||
else:
|
||||
del favicon.failed_urls[entity.domain]
|
||||
|
||||
# 检查缓存
|
||||
_cached, cached_icon = _get_cache_icon(entity.domain_md5, refresh=refresh in ['true', '1'])
|
||||
@@ -74,53 +74,27 @@ async def get_favicon_handler(request: Request,
|
||||
if _cached and not cached_icon:
|
||||
# 缓存已过期,后台刷新缓存
|
||||
logger.info(f"缓存已过期,加入后台队列刷新(异步): {entity.domain}")
|
||||
await redis_pool.set_cache(
|
||||
f"{entity.domain}",
|
||||
entity.domain,
|
||||
setting.time_of_2_hours,
|
||||
prefix=redis_pool.ICON_QUEUE_PREFIX
|
||||
)
|
||||
bg_tasks.add_task(get_icon_async, entity, _cached)
|
||||
|
||||
return Response(content=icon_content,
|
||||
media_type=content_type if content_type else "image/x-icon",
|
||||
headers=_get_header(content_type, cache_time))
|
||||
else:
|
||||
# 开始图标处理,加入队列
|
||||
await redis_pool.set_cache(
|
||||
f"{entity.domain}",
|
||||
entity.domain,
|
||||
setting.time_of_2_hours,
|
||||
prefix=redis_pool.ICON_QUEUE_PREFIX
|
||||
)
|
||||
# 没有缓存,开始图标处理,始终使用异步方法获取图标
|
||||
icon_content = await get_icon_async(entity, _cached)
|
||||
|
||||
# 没有缓存,实时处理,检查队列大小
|
||||
_queue_size = await redis_pool.get_cache_size(prefix=redis_pool.ICON_QUEUE_PREFIX)
|
||||
if _queue_size >= setting.MAX_QUEUE_SIZE:
|
||||
# 加入后台队列并返回默认图片
|
||||
logger.info(
|
||||
f"队列大小({_queue_size})>={setting.MAX_QUEUE_SIZE},返回默认图片并加入后台队列(异步): {entity.domain}")
|
||||
bg_tasks.add_task(get_icon_async, entity, _cached)
|
||||
return get_default(0)
|
||||
else:
|
||||
# 队列<MAX_QUEUE_SIZE,实时处理
|
||||
logger.info(f"队列大小({_queue_size})<{setting.MAX_QUEUE_SIZE},实时处理(异步): {entity.domain}")
|
||||
if not icon_content:
|
||||
# 获取失败,返回默认图标
|
||||
return get_default()
|
||||
|
||||
# 始终使用异步方法获取图标
|
||||
icon_content = await get_icon_async(entity, _cached)
|
||||
# 确定内容类型和缓存时间
|
||||
content_type = filetype.guess_mime(icon_content) if icon_content else ""
|
||||
cache_time = setting.time_of_12_hours \
|
||||
if _is_default_icon_byte(icon_content) else setting.time_of_7_days
|
||||
|
||||
if not icon_content:
|
||||
# 获取失败,返回默认图标
|
||||
return get_default()
|
||||
|
||||
# 确定内容类型和缓存时间
|
||||
content_type = filetype.guess_mime(icon_content) if icon_content else ""
|
||||
cache_time = setting.time_of_12_hours \
|
||||
if _is_default_icon_byte(icon_content) else setting.time_of_7_days
|
||||
|
||||
return Response(content=icon_content,
|
||||
media_type=content_type if content_type else "image/x-icon",
|
||||
headers=_get_header(content_type, cache_time))
|
||||
return Response(content=icon_content,
|
||||
media_type=content_type if content_type else "image/x-icon",
|
||||
headers=_get_header(content_type, cache_time))
|
||||
except Exception as e:
|
||||
logger.error(f"处理图标请求时发生错误 {url}: {e}")
|
||||
# 返回默认图标
|
||||
@@ -164,7 +138,7 @@ async def get_icon_async(entity: Favicon, _cached: bytes = None) -> Optional[byt
|
||||
|
||||
# 图标获取失败,或图标不是支持的图片格式,写入默认图标
|
||||
if (not icon_content) or (not helpers.is_image(icon_content) or _is_default_icon_byte(icon_content)):
|
||||
logger.warning(f"-> 异步获取图标失败,使用默认图标: {entity.domain}")
|
||||
logger.debug(f"-> 异步获取图标失败,使用默认图标: {entity.domain}")
|
||||
icon_content = _cached if _cached else setting.default_icon_file
|
||||
|
||||
if icon_content:
|
||||
@@ -186,8 +160,6 @@ async def get_icon_async(entity: Favicon, _cached: bytes = None) -> Optional[byt
|
||||
except Exception as e:
|
||||
logger.error(f"异步获取图标时发生错误 {entity.domain}: {e}")
|
||||
return _cached or setting.default_icon_file
|
||||
finally:
|
||||
await redis_pool.remove_cache(f"{entity.domain}", prefix=redis_pool.ICON_QUEUE_PREFIX)
|
||||
|
||||
|
||||
# 预编译正则表达式,提高性能
|
||||
|
||||
Reference in New Issue
Block a user