diff --git a/DONATE.md b/DONATE.md index 7a5cc26..57f00f4 100644 --- a/DONATE.md +++ b/DONATE.md @@ -1,4 +1,4 @@ -如果觉得SoulBook对您有帮助,那么您可以给开发者一些支持: +如果觉得对您有帮助,那么您可以给开发者一些支持: - 开源 - 服务器的费用也是一笔开销 diff --git a/Pipfile b/Pipfile index 739e047..dd1b513 100644 --- a/Pipfile +++ b/Pipfile @@ -1,7 +1,8 @@ [[source]] verify_ssl = true name = "pypi" -url = "https://pypi.douban.com/simple/" +#url = "https://pypi.douban.com/simple/" +url = "https://mirrors.aliyun.com/pypi/simple/" [requires] python_version = "3.6" diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..e5d06d5 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +sudo docker build -t guyue55/soulbook . -f docker/Dockerfile-slim \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 19794dd..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,9 +0,0 @@ -version: '3' -services: - web: - image: howie6879/owllook - command: pipenv run gunicorn -c soulbook/config/gunicorn.py --worker-class sanic.worker.GunicornWorker soulbook.server:app - ports: - - "8001:8001" - volumes: - - .:/soulbook \ No newline at end of file diff --git a/docker/Dockerfile-alpine b/docker/Dockerfile-alpine new file mode 100644 index 0000000..d467ff6 --- /dev/null +++ b/docker/Dockerfile-alpine @@ -0,0 +1,25 @@ +# 基于python3.6镜像来构建镜像 +FROM python:3.6-alpine +MAINTAINER guyue55 +ENV TIME_ZONE=Asia/Shanghai + +# 换源 +RUN echo "https://mirrors.aliyun.com/alpine/v3.15/main" > /etc/apk/repositories \ + && echo "https://mirrors.aliyun.com/alpine/v3.15/community" >> /etc/apk/repositories \ + && echo "${TIME_ZONE}" > /etc/timezone \ + && ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime + +# 安装基础库 +RUN apk --no-cache add gcc g++ libc-dev libffi-dev musl-dev cmake build-base + +WORKDIR /app +COPY . . + +#RUN pip install --no-cache-dir --trusted-host mirrors.aliyun.com -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt +RUN pip install --no-cache-dir -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt + +RUN find . -name "*.pyc" -delete + +EXPOSE 8001 + +CMD gunicorn -c soulbook/config/gunicorn.py --worker-class sanic.worker.GunicornWorker soulbook.server:app --log-level=debug \ No newline at end of file diff --git a/Dockerfile b/docker/Dockerfile-old similarity index 100% rename from Dockerfile rename to docker/Dockerfile-old diff --git a/docker/Dockerfile-slim b/docker/Dockerfile-slim new file mode 100644 index 0000000..f6b161d --- /dev/null +++ b/docker/Dockerfile-slim @@ -0,0 +1,16 @@ +# 基于python3.6镜像来构建镜像 +FROM python:3.6-slim +MAINTAINER guyue55 +ENV TIME_ZONE=Asia/Shanghai +RUN echo "${TIME_ZONE}" > /etc/timezone \ + && ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime + +ADD . /app +WORKDIR /app + +RUN pip install --no-cache-dir --trusted-host mirrors.aliyun.com -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt +RUN find . -name "*.pyc" -delete + +EXPOSE 8001 + +CMD gunicorn -c soulbook/config/gunicorn.py --worker-class sanic.worker.GunicornWorker soulbook.server:app --log-level=debug \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..f96d068 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3' +services: + web: + image: guyue55/owllook + command: gunicorn -c soulbook/config/gunicorn.py --worker-class sanic.worker.GunicornWorker soulbook.server:app + ports: + - "8001:8001" + volumes: + - .:/app \ No newline at end of file diff --git a/run_docker.sh b/run_docker.sh new file mode 100644 index 0000000..9eae003 --- /dev/null +++ b/run_docker.sh @@ -0,0 +1,2 @@ +# sudo docker run -it -d -p 8001:8001 -e MONGO_HOST=127.0.0.1 -e MONGO_PORT=27017 -e REDIS_ENDPOINT=127.0.0.1 -e REDIS_PORT=6379 -e REDIS_PASSWORD=password guyue55/soulbook +sudo docker run -it -d -p 8001:8001 --env-file .env guyue55/soulbook \ No newline at end of file diff --git a/soulbook/config/dev_config.py b/soulbook/config/dev_config.py index fe16ee7..2e20a8b 100644 --- a/soulbook/config/dev_config.py +++ b/soulbook/config/dev_config.py @@ -17,24 +17,24 @@ class DevConfig(Config): REDIS_ENDPOINT=os.getenv('REDIS_ENDPOINT', "localhost"), REDIS_PORT=int(os.getenv('REDIS_PORT', 6379)), REDIS_PASSWORD=os.getenv('REDIS_PASSWORD', None), - CACHE_DB=0, - SESSION_DB=1, + CACHE_DB=int(os.getenv('CACHE_DB', 0)), + SESSION_DB=int(os.getenv('SESSION_DB', 1)), POOLSIZE=10, ) MONGODB = dict( MONGO_HOST=os.getenv('MONGO_HOST', "127.0.0.1"), MONGO_PORT=int(os.getenv('MONGO_PORT', 27017)), - MONGO_USERNAME="", - MONGO_PASSWORD="", - DATABASE='soulbook', + MONGO_USERNAME=os.getenv('MONGO_USERNAME', ""), + MONGO_PASSWORD=os.getenv('MONGO_PASSWORD', ""), + DATABASE=os.getenv('MONGO_DB', "soulbook"), ) # website WEBSITE = dict( - IS_RUNNING=os.getenv('OWLLOOK_IS_RUNNING', True), - TOKEN=os.getenv('OWLLOOK_TOKEN', '') + IS_RUNNING=os.getenv('IS_RUNNING', "true").lower() == "true", + TOKEN=os.getenv('TOKEN', '') ) AUTH = { - "Owllook-Api-Key": os.getenv('OWLLOOK_API_KEY', "your key") + "Owllook-Api-Key": os.getenv('API_KEY', "your key") } diff --git a/soulbook/fetcher/decorators.py b/soulbook/fetcher/decorators.py index a1fa8a5..9a4f2fd 100644 --- a/soulbook/fetcher/decorators.py +++ b/soulbook/fetcher/decorators.py @@ -23,18 +23,30 @@ from soulbook.config import CONFIG, LOGGER def authenticator(key): """ + 验证请求头中的特定键值对是否与配置中的值匹配 - :param keys: 验证方式 Owllook-Api-Key : Magic Key, Authorization : Token - :return: 返回值 + :param key: 需要验证的请求头键名,例如 "Owllook-Api-Key" 或 "Authorization" + :return: 装饰器函数,用于验证请求头中的键值对 """ def wrapper(func): @wraps(func) async def authenticate(request, *args, **kwargs): + """ + 验证请求头中的键值对是否与配置中的值匹配 + + :param request: Sanic 请求对象 + :param args: 位置参数 + :param kwargs: 关键字参数 + :return: 如果验证成功,返回被装饰函数的结果;否则返回未授权的响应 + """ + # 从请求头中获取指定键的值 value = request.headers.get(key, None) + # 如果值存在且与配置中的值匹配,则调用被装饰的函数 if value and CONFIG.AUTH[key] == value: response = await func(request, *args, **kwargs) return response + # 如果值不存在或与配置中的值不匹配,则返回未授权的响应 else: return response_handle(request, UniResponse.NOT_AUTHORIZED, status=401) @@ -108,35 +120,61 @@ def cached( :param plugins: plugins to use when calling the cmd hooks Default is the one configured in ``aiocache.settings.DEFAULT_PLUGINS`` """ + # 将传入的关键字参数存储在 cache_kwargs 中,以便后续使用 cache_kwargs = kwargs def cached_decorator(func): + """ + 装饰器函数,用于缓存函数的返回值 + + :param func: 被装饰的函数 + :return: 包装后的函数 + """ async def wrapper(*args, **kwargs): + """ + 包装后的函数,用于执行缓存逻辑 + + :param args: 位置参数 + :param kwargs: 关键字参数 + :return: 函数的返回值 + """ + # 获取缓存实例,使用传入的参数或默认配置 cache_instance = get_cache( cache=cache, serializer=serializer, plugins=plugins, **cache_kwargs) + # 获取函数的参数字典 args_dict = get_args_dict(func, args, kwargs) + # 生成缓存键,如果没有指定 key,则使用函数名、参数和关键字参数生成 cache_key = key or args_dict.get( key_from_attr, (func.__module__ or 'stub') + func.__name__ + str(args) + str(kwargs)) try: + # 检查缓存中是否存在该键 if await cache_instance.exists(cache_key): + # 如果存在,从缓存中获取值并返回 return await cache_instance.get(cache_key) except Exception: + # 如果发生异常,记录日志 logger.exception("Unexpected error with %s", cache_instance) + # 如果缓存中不存在该键,调用原始函数获取结果 result = await func(*args, **kwargs) if result: try: + # 将结果存入缓存 await cache_instance.set(cache_key, result, ttl=ttl) except Exception: + # 如果发生异常,记录日志 logger.exception("Unexpected error with %s", cache_instance) + # 返回函数的结果 return result + # 返回包装后的函数 return wrapper + # 返回装饰器函数 return cached_decorator