25.09.04
parent
38c681b553
commit
0b1c3fddcd
|
@ -34,6 +34,6 @@ if [ ! -f "$logging_conf" ]; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p /app/logs /app/data/icon /app/data/text
|
mkdir -p /app/logs /app/data
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|
|
@ -54,13 +54,21 @@ async def get_count():
|
||||||
|
|
||||||
|
|
||||||
@favicon_router.get('/icon/referer', include_in_schema=False)
|
@favicon_router.get('/icon/referer', include_in_schema=False)
|
||||||
async def get_referrer():
|
async def get_referrer(unique: Optional[str] = Query(None)):
|
||||||
"""获取请求来源信息"""
|
"""获取请求来源信息,带unique参数时会进行去重处理"""
|
||||||
content = 'None'
|
content = 'None'
|
||||||
path = os.path.join(_icon_root_path, 'data', 'referer.txt')
|
path = os.path.join(_icon_root_path, 'data', 'referer.txt')
|
||||||
|
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
try:
|
try:
|
||||||
content = FileUtil.read_file(path, mode='r') or 'None'
|
content = FileUtil.read_file(path, mode='r') or 'None'
|
||||||
|
|
||||||
|
if unique in ['true', '1', 'True']:
|
||||||
|
lines = [line.strip() for line in content.split('\n') if line.strip()]
|
||||||
|
unique_lines = list(set(lines))
|
||||||
|
unique_content = '\n'.join(unique_lines)
|
||||||
|
FileUtil.write_file(path, unique_content, mode='w')
|
||||||
|
content = unique_content
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"读取referer文件失败: {e}")
|
logger.error(f"读取referer文件失败: {e}")
|
||||||
return Response(content=content, media_type="text/plain")
|
return Response(content=content, media_type="text/plain")
|
||||||
|
|
|
@ -39,6 +39,7 @@ class FaviconService:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# 使用锁保证线程安全
|
# 使用锁保证线程安全
|
||||||
self._lock = Lock()
|
self._lock = Lock()
|
||||||
|
|
||||||
# 全局计数器和集合
|
# 全局计数器和集合
|
||||||
self.url_count = 0
|
self.url_count = 0
|
||||||
self.request_icon_count = 0
|
self.request_icon_count = 0
|
||||||
|
@ -46,7 +47,9 @@ class FaviconService:
|
||||||
self.domain_list: List[str] = list()
|
self.domain_list: List[str] = list()
|
||||||
|
|
||||||
# 初始化队列
|
# 初始化队列
|
||||||
|
# 实时处理的任务数量
|
||||||
self.icon_queue = Queue()
|
self.icon_queue = Queue()
|
||||||
|
# 所有正在处理的任务数量
|
||||||
self.total_queue = Queue()
|
self.total_queue = Queue()
|
||||||
|
|
||||||
# 队列阈值常量配置
|
# 队列阈值常量配置
|
||||||
|
@ -193,12 +196,14 @@ class FaviconService:
|
||||||
}
|
}
|
||||||
|
|
||||||
def _queue_pull(self, is_pull: bool = True, _queue: Queue = None) -> None:
|
def _queue_pull(self, is_pull: bool = True, _queue: Queue = None) -> None:
|
||||||
"""从队列中取出元素"""
|
"""从队列中取出元素,用于任务完成后移除队列中的记录
|
||||||
|
- is_pull: 是否执行取出操作
|
||||||
|
- _queue: 要操作的队列,默认为icon_queue
|
||||||
|
"""
|
||||||
if _queue is None:
|
if _queue is None:
|
||||||
_queue = self.icon_queue
|
_queue = self.icon_queue
|
||||||
|
|
||||||
if is_pull and not _queue.empty():
|
if is_pull and not _queue.empty():
|
||||||
# _queue.get()
|
|
||||||
try:
|
try:
|
||||||
_queue.get_nowait()
|
_queue.get_nowait()
|
||||||
_queue.task_done()
|
_queue.task_done()
|
||||||
|
@ -269,7 +274,6 @@ class FaviconService:
|
||||||
icon_content = None
|
icon_content = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
if entity.domain in self.domain_list:
|
if entity.domain in self.domain_list:
|
||||||
self._queue_pull(True, self.total_queue)
|
self._queue_pull(True, self.total_queue)
|
||||||
|
@ -340,6 +344,8 @@ class FaviconService:
|
||||||
with self._lock:
|
with self._lock:
|
||||||
if entity.domain in self.domain_list:
|
if entity.domain in self.domain_list:
|
||||||
self.domain_list.remove(entity.domain)
|
self.domain_list.remove(entity.domain)
|
||||||
|
# 同时从两个队列中移除元素(处理完成)
|
||||||
|
self._queue_pull(True, self.icon_queue)
|
||||||
self._queue_pull(True, self.total_queue)
|
self._queue_pull(True, self.total_queue)
|
||||||
|
|
||||||
def get_count(self) -> Dict[str, int]:
|
def get_count(self) -> Dict[str, int]:
|
||||||
|
@ -369,7 +375,6 @@ class FaviconService:
|
||||||
if not url:
|
if not url:
|
||||||
return {"message": "请提供url参数"}
|
return {"message": "请提供url参数"}
|
||||||
|
|
||||||
logger.info('##########################################################')
|
|
||||||
try:
|
try:
|
||||||
entity = Favicon(url)
|
entity = Favicon(url)
|
||||||
|
|
||||||
|
@ -396,6 +401,8 @@ class FaviconService:
|
||||||
if _cached and not cached_icon:
|
if _cached and not cached_icon:
|
||||||
# 缓存已过期,后台刷新缓存
|
# 缓存已过期,后台刷新缓存
|
||||||
logger.info(f"缓存已过期,加入后台队列刷新: {entity.domain}")
|
logger.info(f"缓存已过期,加入后台队列刷新: {entity.domain}")
|
||||||
|
# 只增加总队列计数,不增加实时队列计数(后台任务)
|
||||||
|
self.total_queue.put(entity.domain)
|
||||||
bg_tasks.add_task(self.get_icon_sync, entity, _cached)
|
bg_tasks.add_task(self.get_icon_sync, entity, _cached)
|
||||||
|
|
||||||
return Response(content=icon_content,
|
return Response(content=icon_content,
|
||||||
|
@ -408,6 +415,8 @@ class FaviconService:
|
||||||
if not is_sync:
|
if not is_sync:
|
||||||
# 返回默认图片并加入后台队列
|
# 返回默认图片并加入后台队列
|
||||||
logger.info(f"返回默认图片并加入后台队列: {entity.domain}")
|
logger.info(f"返回默认图片并加入后台队列: {entity.domain}")
|
||||||
|
# 只增加总队列计数,不增加实时队列计数(后台任务)
|
||||||
|
self.total_queue.put(entity.domain)
|
||||||
bg_tasks.add_task(self.get_icon_sync, entity, _cached)
|
bg_tasks.add_task(self.get_icon_sync, entity, _cached)
|
||||||
return self.get_default(0)
|
return self.get_default(0)
|
||||||
else:
|
else:
|
||||||
|
@ -416,11 +425,16 @@ class FaviconService:
|
||||||
if queue_size >= self.MAX_QUEUE_SIZE:
|
if queue_size >= self.MAX_QUEUE_SIZE:
|
||||||
# 加入后台队列并返回默认图片
|
# 加入后台队列并返回默认图片
|
||||||
logger.info(f"队列大小({queue_size})>={self.MAX_QUEUE_SIZE},返回默认图片并加入后台队列: {entity.domain}")
|
logger.info(f"队列大小({queue_size})>={self.MAX_QUEUE_SIZE},返回默认图片并加入后台队列: {entity.domain}")
|
||||||
|
# 只增加总队列计数,不增加实时队列计数(后台任务)
|
||||||
|
self.total_queue.put(entity.domain)
|
||||||
bg_tasks.add_task(self.get_icon_sync, entity, _cached)
|
bg_tasks.add_task(self.get_icon_sync, entity, _cached)
|
||||||
return self.get_default(0)
|
return self.get_default(0)
|
||||||
else:
|
else:
|
||||||
# 队列<MAX_QUEUE_SIZE,实时处理
|
# 队列<MAX_QUEUE_SIZE,实时处理
|
||||||
logger.info(f"队列大小({queue_size})<{self.MAX_QUEUE_SIZE},实时处理: {entity.domain}")
|
logger.info(f"队列大小({queue_size})<{self.MAX_QUEUE_SIZE},实时处理: {entity.domain}")
|
||||||
|
# 同时增加两个队列计数(实时处理任务)
|
||||||
|
self.icon_queue.put(entity.domain)
|
||||||
|
self.total_queue.put(entity.domain)
|
||||||
icon_content = self.get_icon_sync(entity, _cached)
|
icon_content = self.get_icon_sync(entity, _cached)
|
||||||
|
|
||||||
if not icon_content:
|
if not icon_content:
|
||||||
|
|
6
main.py
6
main.py
|
@ -30,15 +30,17 @@ app.include_router(favicon_router)
|
||||||
|
|
||||||
@app.middleware("http")
|
@app.middleware("http")
|
||||||
async def log_referer(request: Request, call_next):
|
async def log_referer(request: Request, call_next):
|
||||||
|
_flag = True if ('/icon' in request.url.path and 'url=' in request.url.query) else False
|
||||||
|
logger.info('#' * 60) if _flag else None
|
||||||
referer = request.headers.get('referrer') or request.headers.get('referer')
|
referer = request.headers.get('referrer') or request.headers.get('referer')
|
||||||
if referer:
|
if referer:
|
||||||
FileUtil.write_file(referer_log_file, referer, mode='a', atomic=True)
|
FileUtil.write_file(referer_log_file, referer, mode='a', atomic=True)
|
||||||
response = await call_next(request)
|
response = await call_next(request)
|
||||||
|
logger.info('#' * 60) if _flag else None
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
# @app.get("/")
|
@app.get("/")
|
||||||
async def root():
|
async def root():
|
||||||
return {"message": "Welcome to Favicon API! Use /icon/?url=example.com to get favicon."}
|
return {"message": "Welcome to Favicon API! Use /icon/?url=example.com to get favicon."}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue