25.09.03
parent
a5290c5e03
commit
452e110ee5
|
@ -0,0 +1,19 @@
|
||||||
|
# 忽略所有隐藏文件
|
||||||
|
.*
|
||||||
|
|
||||||
|
# 忽略构建产物
|
||||||
|
dist/
|
||||||
|
*.egg-info/
|
||||||
|
|
||||||
|
# 忽略本地依赖
|
||||||
|
node_modules/
|
||||||
|
venv/
|
||||||
|
.pipenv/
|
||||||
|
|
||||||
|
# 忽略临时文件
|
||||||
|
*.tmp
|
||||||
|
*.log
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
|
# 忽略指定目录
|
||||||
|
data/
|
|
@ -165,4 +165,4 @@ cython_debug/
|
||||||
!/.vscode/
|
!/.vscode/
|
||||||
.vscode/
|
.vscode/
|
||||||
icon/*
|
icon/*
|
||||||
md5/*
|
data/*
|
||||||
|
|
|
@ -29,5 +29,9 @@ RUN find . -name "*.py" -delete
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
|
VOLUME ["/app/data", "/app/conf", "/app/logs"]
|
||||||
|
|
||||||
|
ENTRYPOINT ["entrypoint.sh"]
|
||||||
|
|
||||||
# CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
# CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
CMD ["gunicorn", "--config", "gunicorn.conf.pyc", "main:app"]
|
CMD ["gunicorn", "-c", "conf/gunicorn.conf.pyc", "main:app"]
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
# 绑定地址和端口
|
||||||
|
bind = "0.0.0.0:8000"
|
||||||
|
|
||||||
|
# Worker 进程数(推荐 CPU 核心数 * 2 + 1)
|
||||||
|
workers = 1
|
||||||
|
|
||||||
|
# 工作模式(sync、gevent、uvicorn.workers.UvicornWorker)
|
||||||
|
worker_class = "uvicorn.workers.UvicornWorker"
|
||||||
|
|
||||||
|
# 日志目录
|
||||||
|
log_dir = Path("logs")
|
||||||
|
log_dir.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
with open(Path(__file__).with_name("logging.yaml"), "r", encoding="utf-8") as f:
|
||||||
|
logconfig_dict = yaml.safe_load(f)
|
||||||
|
|
||||||
|
# 日志级别(debug、info、warning、error、critical);以 YAML 配置优先
|
||||||
|
loglevel = "info"
|
||||||
|
|
||||||
|
# 访问日志文件("-" 表示输出到 stdout);以 YAML 配置优先
|
||||||
|
accesslog = "logs/access.log"
|
||||||
|
|
||||||
|
# 错误日志文件;以 YAML 配置优先
|
||||||
|
errorlog = "-"
|
||||||
|
|
||||||
|
# access_log_format 仅在 同步 worker 下有效,UvicornWorker下不可用;以 YAML 配置优先
|
||||||
|
# access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s'
|
||||||
|
raw_env = [
|
||||||
|
"UVICORN_ACCESS_LOGFORMAT=%(h)s %(l)s %(u)s %(t)s \"%(r)s\" %(s)s %(b)s \"%(f)s\" \"%(a)s\" %(D)s"
|
||||||
|
]
|
||||||
|
|
||||||
|
# 可选:超时时间(秒)
|
||||||
|
timeout = 120
|
||||||
|
|
||||||
|
# Keep - Alive超时
|
||||||
|
keepalive = 5
|
||||||
|
|
||||||
|
# 进程名(ps aux 中显示)
|
||||||
|
# proc_name = "gunicorn"
|
||||||
|
|
||||||
|
# 守护进程运行(后台运行,默认 False)
|
||||||
|
# daemon = True
|
|
@ -0,0 +1,60 @@
|
||||||
|
version: 1
|
||||||
|
disable_existing_loggers: false
|
||||||
|
formatters:
|
||||||
|
default:
|
||||||
|
format: "[%(levelname)-7s] %(asctime)s [%(process)d] -[%(name)s:%(lineno)d] %(message)s"
|
||||||
|
datefmt: "%Y-%m-%d %H:%M:%S"
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
console:
|
||||||
|
class: logging.StreamHandler
|
||||||
|
level: INFO
|
||||||
|
formatter: default
|
||||||
|
stream: ext://sys.stdout
|
||||||
|
file_info:
|
||||||
|
class: logging.handlers.TimedRotatingFileHandler
|
||||||
|
level: INFO
|
||||||
|
formatter: default
|
||||||
|
filename: logs/info.log
|
||||||
|
when: midnight
|
||||||
|
interval: 1
|
||||||
|
backupCount: 7
|
||||||
|
encoding: utf8
|
||||||
|
delay: true
|
||||||
|
file_error:
|
||||||
|
class: logging.handlers.TimedRotatingFileHandler
|
||||||
|
level: ERROR
|
||||||
|
formatter: default
|
||||||
|
filename: logs/error.log
|
||||||
|
when: midnight
|
||||||
|
interval: 1
|
||||||
|
backupCount: 7
|
||||||
|
encoding: utf8
|
||||||
|
delay: true
|
||||||
|
|
||||||
|
loggers:
|
||||||
|
uvicorn:
|
||||||
|
level: INFO
|
||||||
|
handlers:
|
||||||
|
- console
|
||||||
|
- file_info
|
||||||
|
propagate: false
|
||||||
|
uvicorn.error:
|
||||||
|
level: INFO
|
||||||
|
handlers:
|
||||||
|
- console
|
||||||
|
- file_error
|
||||||
|
propagate: false
|
||||||
|
uvicorn.access:
|
||||||
|
level: INFO
|
||||||
|
handlers:
|
||||||
|
- console
|
||||||
|
- file_info
|
||||||
|
propagate: false
|
||||||
|
|
||||||
|
root:
|
||||||
|
level: INFO
|
||||||
|
handlers:
|
||||||
|
- console
|
||||||
|
- file_info
|
||||||
|
- file_error
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 首次启动时把镜像里的默认配置拷到挂载点
|
||||||
|
[ -z "$(ls -A /app/conf)" ] && cp -r /app/conf.default/* /app/conf/
|
||||||
|
|
||||||
|
exec "$@"
|
|
@ -20,7 +20,7 @@ from favicon_app.utils.filetype import helpers, filetype
|
||||||
urllib3.disable_warnings()
|
urllib3.disable_warnings()
|
||||||
logging.captureWarnings(True)
|
logging.captureWarnings(True)
|
||||||
# 配置日志
|
# 配置日志
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# 创建requests会话池
|
# 创建requests会话池
|
||||||
requests_session = requests.Session()
|
requests_session = requests.Session()
|
||||||
|
|
|
@ -13,7 +13,7 @@ from favicon_app.utils.file_util import FileUtil
|
||||||
|
|
||||||
urllib3.disable_warnings()
|
urllib3.disable_warnings()
|
||||||
logging.captureWarnings(True)
|
logging.captureWarnings(True)
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_icon_root_path = favicon_service.icon_root_path
|
_icon_root_path = favicon_service.icon_root_path
|
||||||
_default_icon_path = favicon_service.default_icon_path
|
_default_icon_path = favicon_service.default_icon_path
|
||||||
|
@ -58,7 +58,7 @@ async def get_count():
|
||||||
async def get_referrer():
|
async def get_referrer():
|
||||||
"""获取请求来源信息"""
|
"""获取请求来源信息"""
|
||||||
content = 'None'
|
content = 'None'
|
||||||
path = os.path.join(_icon_root_path, 'referrer.txt')
|
path = os.path.join(_icon_root_path, 'conf', 'referrer.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'
|
||||||
|
|
|
@ -23,7 +23,7 @@ from favicon_app.utils.filetype import helpers, filetype
|
||||||
|
|
||||||
urllib3.disable_warnings()
|
urllib3.disable_warnings()
|
||||||
logging.captureWarnings(True)
|
logging.captureWarnings(True)
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# 获取当前所在目录的绝对路径
|
# 获取当前所在目录的绝对路径
|
||||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
@ -127,7 +127,7 @@ class FaviconService:
|
||||||
|
|
||||||
def _get_cache_file(self, domain: str, refresh: bool = False) -> Tuple[Optional[bytes], Optional[bytes]]:
|
def _get_cache_file(self, domain: str, refresh: bool = False) -> Tuple[Optional[bytes], Optional[bytes]]:
|
||||||
"""从缓存中获取图标文件"""
|
"""从缓存中获取图标文件"""
|
||||||
cache_path = os.path.join(icon_root_path, 'icon', domain + '.png')
|
cache_path = os.path.join(icon_root_path, 'data/icon', domain + '.png')
|
||||||
if os.path.exists(cache_path) and os.path.isfile(cache_path) and os.path.getsize(cache_path) > 0:
|
if os.path.exists(cache_path) and os.path.isfile(cache_path) and os.path.getsize(cache_path) > 0:
|
||||||
try:
|
try:
|
||||||
cached_icon = FileUtil.read_file(cache_path, mode='rb')
|
cached_icon = FileUtil.read_file(cache_path, mode='rb')
|
||||||
|
@ -269,7 +269,7 @@ class FaviconService:
|
||||||
if _referrer:
|
if _referrer:
|
||||||
logger.debug(f"-> Referrer: {_referrer}")
|
logger.debug(f"-> Referrer: {_referrer}")
|
||||||
|
|
||||||
_path = os.path.join(icon_root_path, 'referrer.txt')
|
_path = os.path.join(icon_root_path, 'conf', 'referrer.txt')
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
# 首次加载现有referrer数据
|
# 首次加载现有referrer数据
|
||||||
|
@ -336,8 +336,8 @@ class FaviconService:
|
||||||
icon_content = _cached if _cached else default_icon_content
|
icon_content = _cached if _cached else default_icon_content
|
||||||
|
|
||||||
if icon_content:
|
if icon_content:
|
||||||
cache_path = os.path.join(icon_root_path, 'icon', entity.domain_md5 + '.png')
|
cache_path = os.path.join(icon_root_path, 'data/icon', entity.domain_md5 + '.png')
|
||||||
md5_path = os.path.join(icon_root_path, 'md5', entity.domain_md5 + '.txt')
|
md5_path = os.path.join(icon_root_path, 'data/text', entity.domain_md5 + '.txt')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 确保目录存在
|
# 确保目录存在
|
||||||
|
@ -391,6 +391,7 @@ class FaviconService:
|
||||||
if not url:
|
if not url:
|
||||||
return {"message": "请提供url参数"}
|
return {"message": "请提供url参数"}
|
||||||
|
|
||||||
|
logger.info('##########################################################')
|
||||||
try:
|
try:
|
||||||
entity = Favicon(url)
|
entity = Favicon(url)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import urllib3
|
||||||
# 配置日志
|
# 配置日志
|
||||||
urllib3.disable_warnings()
|
urllib3.disable_warnings()
|
||||||
logging.captureWarnings(True)
|
logging.captureWarnings(True)
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class FileUtil:
|
class FileUtil:
|
||||||
|
@ -244,7 +244,7 @@ class FileUtil:
|
||||||
with open(file_path, mode, encoding=encoding) as f:
|
with open(file_path, mode, encoding=encoding) as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
|
|
||||||
logger.info(f"文件写入成功: {file_path}")
|
# logger.info(f"文件写入成功: {file_path}")
|
||||||
return True
|
return True
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
logger.error(f"没有权限写入文件: {file_path}")
|
logger.error(f"没有权限写入文件: {file_path}")
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# 绑定地址和端口
|
|
||||||
bind = "0.0.0.0:8000"
|
|
||||||
|
|
||||||
# Worker 进程数(推荐 CPU 核心数 * 2 + 1)
|
|
||||||
workers = 4
|
|
||||||
|
|
||||||
# 工作模式(sync、gevent、uvicorn.workers.UvicornWorker)
|
|
||||||
worker_class = "uvicorn.workers.UvicornWorker"
|
|
||||||
|
|
||||||
# 日志级别(debug、info、warning、error、critical)
|
|
||||||
loglevel = "info"
|
|
||||||
|
|
||||||
# 访问日志文件("-" 表示输出到 stdout)
|
|
||||||
accesslog = "-"
|
|
||||||
|
|
||||||
# 错误日志文件
|
|
||||||
errorlog = "-"
|
|
||||||
|
|
||||||
# 可选:超时时间(秒)
|
|
||||||
timeout = 120
|
|
||||||
|
|
||||||
# Keep - Alive超时
|
|
||||||
keepalive = 5
|
|
||||||
|
|
||||||
# 进程名(ps aux 中显示)
|
|
||||||
# proc_name = "gunicorn"
|
|
||||||
|
|
||||||
# 守护进程运行(后台运行,默认 False)
|
|
||||||
# daemon = True
|
|
4
main.py
4
main.py
|
@ -10,9 +10,7 @@ from fastapi.responses import Response
|
||||||
from favicon_app.routes import favicon_router
|
from favicon_app.routes import favicon_router
|
||||||
from favicon_app.utils.file_util import FileUtil
|
from favicon_app.utils.file_util import FileUtil
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO,
|
logger = logging.getLogger(__name__)
|
||||||
format='[%(levelname)-7s] %(asctime)s -[%(filename)-10.10s:%(lineno)4d] %(message)s',
|
|
||||||
filename='favicon-app.log')
|
|
||||||
|
|
||||||
# 获取当前所在目录
|
# 获取当前所在目录
|
||||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
|
@ -6,5 +6,6 @@ requests~=2.32.5
|
||||||
bs4~=0.0.2
|
bs4~=0.0.2
|
||||||
beautifulsoup4~=4.13.5
|
beautifulsoup4~=4.13.5
|
||||||
lxml~=6.0.1
|
lxml~=6.0.1
|
||||||
|
PyYAML~=6.0.2
|
||||||
uvicorn~=0.35.0
|
uvicorn~=0.35.0
|
||||||
gunicorn~=23.0.0
|
gunicorn~=23.0.0
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
gunicorn main:app -c gunicorn.conf.py
|
gunicorn -c conf/gunicorn.conf.py main:app
|
||||||
|
|
Loading…
Reference in New Issue