init
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import base64
|
||||
import hmac
|
||||
import json
|
||||
import time
|
||||
from typing import Optional
|
||||
from core.basic.character import Character
|
||||
from fastapi import Header, Request
|
||||
from api.core.exception import ResponseException
|
||||
|
||||
|
||||
class AlterState:
|
||||
def __init__(self, alter: str, token: str, charcater: Character, equVersion: str):
|
||||
self.alter = alter
|
||||
self.token = token
|
||||
self.origin = alter.split('.')[-1]
|
||||
self.character = charcater
|
||||
self.equVersion = equVersion
|
||||
|
||||
def to_dict(self):
|
||||
return self.__dict__
|
||||
|
||||
|
||||
class Dict(dict):
|
||||
__setattr__ = dict.__setitem__
|
||||
__getattr__ = dict.__getitem__
|
||||
|
||||
|
||||
def dict2obj(dictObj):
|
||||
if not isinstance(dictObj, dict):
|
||||
return dictObj
|
||||
d = Dict()
|
||||
for k, v in dictObj.items():
|
||||
d[k] = dict2obj(v)
|
||||
return d
|
||||
|
||||
|
||||
async def createToken(alter: str, equVersion: str, expire=86400 / 24 * 2, redis=None, env=''):
|
||||
ts_str = str(time.time() + expire)
|
||||
ts_byte = ts_str.encode('utf-8')
|
||||
sha1_tshex_str = hmac.new(alter.encode('utf-8'), ts_byte, 'sha1').hexdigest()
|
||||
token = sha1_tshex_str
|
||||
token = base64.urlsafe_b64encode(token.encode('utf-8')).decode('utf-8')
|
||||
# character = createCharacter(alter)
|
||||
character = {}
|
||||
await redis.set(f'token:{token}', json.dumps(AlterState(alter, token, character, equVersion).to_dict()), int(expire))
|
||||
return token
|
||||
|
||||
|
||||
async def readToken(token: str, redis, env) -> AlterState:
|
||||
info = None
|
||||
try:
|
||||
info = dict2obj(json.loads(await redis.get(f'token:{token}')))
|
||||
except Exception:
|
||||
ResponseException('登录过期或无效Token,请刷新后重试')
|
||||
if info is None:
|
||||
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
||||
return info
|
||||
|
||||
|
||||
def deleteToken(token, redis, env):
|
||||
redis.expire(token, 0)
|
||||
return token
|
||||
|
||||
|
||||
async def authorize(request: Request, access_token: Optional[str] = Header(None)):
|
||||
if access_token is not None:
|
||||
info = await readToken(access_token, request.app.state.redis, request.app.state.env)
|
||||
return info
|
||||
else:
|
||||
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
||||
|
||||
|
||||
def unauthorize(request: Request, access_token: Optional[str] = Header(None)):
|
||||
if access_token is not None:
|
||||
return deleteToken(access_token, request.app.state.redis, request.app.state.env)
|
||||
|
||||
|
||||
async def uid(request: Request, access_uid: Optional[str] = Header(None)):
|
||||
try:
|
||||
return int(access_uid)
|
||||
except Exception:
|
||||
return -1
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import traceback
|
||||
from fastapi import Request, status
|
||||
from fastapi.responses import JSONResponse
|
||||
# from fastapi import Request, status
|
||||
|
||||
from api.core.exception import ResponseException
|
||||
|
||||
logFormatter = logging.Formatter(
|
||||
"""
|
||||
[start]
|
||||
%(asctime)s
|
||||
<%(name)s>
|
||||
%(message)s
|
||||
[end]
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
async def all_exception_handler(request: Request, ex: Exception):
|
||||
# api = str(request.url).split("api/")[1]
|
||||
info = ''
|
||||
if not isinstance(ex, ResponseException):
|
||||
info = traceback.format_exc(limit=-1).strip().split('\n')[1:]
|
||||
info[0] = info[0].split('\\')[-1].replace('"', ':').replace(',', '')
|
||||
info = '\r'.join(info)
|
||||
if request.client.host != '127.0.0.1':
|
||||
from fastapi.logger import logger
|
||||
|
||||
logger.setLevel(logging.ERROR)
|
||||
logger.name = 'dcalc'
|
||||
log_directory = 'logs'
|
||||
import os
|
||||
|
||||
if not os.path.exists('./logs'):
|
||||
os.makedirs('./logs')
|
||||
time_str = datetime.now().strftime('%Y_%m_%d')
|
||||
fileHandler = logging.FileHandler(f'{log_directory}/{logger.name,}_{time_str}.log', encoding='utf-8')
|
||||
fileHandler.setFormatter(logFormatter)
|
||||
fileHandler.setLevel(logging.ERROR)
|
||||
logger.addHandler(fileHandler)
|
||||
try:
|
||||
import pathlib
|
||||
|
||||
pathlib.Path(log_directory).mkdir(parents=True, exist_ok=True)
|
||||
except PermissionError:
|
||||
print('创建日志目录logs失败,请确认是否限制了基础的运行权限')
|
||||
logFunc = logger.error
|
||||
logFunc(info)
|
||||
info = '服务器内部错误'
|
||||
else:
|
||||
info = ex.args[0]
|
||||
# traceback.print_last(sys.exc_info())
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
# 一定要加
|
||||
headers={'Access-Control-Allow-Origin': '*'},
|
||||
content={
|
||||
'code': 500,
|
||||
'message': info,
|
||||
# f"api:{api} \n \r{info}",
|
||||
'data': [],
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,56 @@
|
||||
import gzip
|
||||
from fastapi import Request, APIRouter, FastAPI
|
||||
from fastapi.responses import Response
|
||||
from typing import Callable
|
||||
from fastapi.middleware.gzip import GZipMiddleware
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
|
||||
class GzipRequest(Request):
|
||||
async def body(self) -> bytes:
|
||||
if not hasattr(self, '_body'):
|
||||
body = await super().body()
|
||||
if 'gzip' in self.headers.getlist('Content-Encoding'):
|
||||
body = gzip.decompress(body)
|
||||
if 'application/json;charset=UTF-8' in self.headers.getlist('Content-Type'):
|
||||
body = body.decode()
|
||||
pass
|
||||
self._body = body
|
||||
return self._body
|
||||
|
||||
|
||||
class GzipRoute(APIRoute):
|
||||
def get_route_handler(self) -> Callable:
|
||||
original_route_handler = super().get_route_handler()
|
||||
|
||||
async def custom_route_handler(request: Request) -> Response:
|
||||
request = GzipRequest(request.scope, request.receive)
|
||||
return await original_route_handler(request)
|
||||
|
||||
return custom_route_handler
|
||||
|
||||
|
||||
def register_gzip_request(router: APIRouter):
|
||||
router.route_class = GzipRoute
|
||||
pass
|
||||
|
||||
|
||||
def register_gzip_response(app: FastAPI):
|
||||
app.add_middleware(GZipMiddleware)
|
||||
pass
|
||||
|
||||
def gzip_zip(content):
|
||||
bytes_com = gzip.compress(str(content).encode('utf-8'))
|
||||
# base64_data = base64.b64encode(bytes_com)
|
||||
# back = base64_data.decode()
|
||||
return bytes_com
|
||||
|
||||
|
||||
def gzip_unzip(content):
|
||||
if content:
|
||||
# base64_data = base64.b64decode(content)
|
||||
bytes_decom = gzip.decompress(content)
|
||||
str_unzip = bytes_decom.decode()
|
||||
return str_unzip
|
||||
else:
|
||||
return None
|
||||
@@ -0,0 +1,21 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
|
||||
def register_cors(app: FastAPI):
|
||||
"""
|
||||
支持跨域
|
||||
:param app:
|
||||
:return:
|
||||
"""
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
# allow_origins = ["http://127.0.0.1:25252"],
|
||||
# allow_origin_regex='https?://(127.0.0.1|localhost|.*.skycity.top|.*.dnftools.com):?.*', # 改成用正则就行了
|
||||
# 改成用正则就行了
|
||||
allow_origin_regex='https?://(127.0.0.1|localhost|.*.dnftools.com|.*.dcalc.cn):?.*',
|
||||
allow_credentials=True,
|
||||
allow_methods=['*'],
|
||||
allow_headers=['*'],
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
import json
|
||||
from api.core.Gzip import gzip_zip, gzip_unzip
|
||||
|
||||
def get_redis_info(redis, key, fun,without_gzip=False):
|
||||
info = None
|
||||
if redis:
|
||||
try:
|
||||
if without_gzip:
|
||||
info = json.loads(redis.get(key))
|
||||
else:
|
||||
info = json.loads(gzip_unzip(redis.get(key)))
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
info = None
|
||||
if info is None:
|
||||
info = fun()
|
||||
if redis and info is not None:
|
||||
if without_gzip:
|
||||
redis.set(key, json.dumps(info))
|
||||
else:
|
||||
redis.set(key, gzip_zip(json.dumps(info)))
|
||||
return info
|
||||
@@ -0,0 +1,41 @@
|
||||
import base64
|
||||
import json
|
||||
from typing import Generic, TypeVar, Union
|
||||
from pydantic.generics import GenericModel
|
||||
import gzip # 导入 gzip 模块
|
||||
from io import BytesIO # 从 io 模块导入 BytesIO 类
|
||||
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
class Return(GenericModel, Generic[T]):
|
||||
code: int = 200
|
||||
message: str = ''
|
||||
data: Union[T, dict, str] = None
|
||||
|
||||
|
||||
|
||||
# 定义一个函数,将字符串压缩为 gzip 格式,并进行 base64 编码后返回结果
|
||||
def gzip_str(to_gzip: str) -> str:
|
||||
out = BytesIO() # 创建一个 BytesIO 对象
|
||||
with gzip.GzipFile(fileobj=out, mode='w') as f: # 使用 gzip 对象进行数据压缩
|
||||
f.write(to_gzip.encode()) # 将待压缩的字符串写入 gzip 对象中
|
||||
return base64.b64encode(out.getvalue()).decode() # 对压缩后的数据使用 base64 编码并返回结果
|
||||
|
||||
|
||||
def response(*, code=200, data: Union[list, dict, str], message='Success', zip=False):
|
||||
if zip:
|
||||
import gzip
|
||||
data = base64.b64encode(gzip.compress(json.dumps(data).encode()))
|
||||
return Return(code=code, message=message, data=data)
|
||||
|
||||
|
||||
def success(data=None, msg=''):
|
||||
"""成功返回格式"""
|
||||
return response(200, msg, data)
|
||||
|
||||
|
||||
def fail(code=-1, msg='', data=None):
|
||||
"""失败返回格式"""
|
||||
return response(code, msg, data)
|
||||
@@ -0,0 +1,2 @@
|
||||
class ResponseException(Exception):
|
||||
pass
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user