pre / app.py
yangtb24's picture
Upload 61 files
99fc92f verified
"""
API密钥管理系统 - 主应用文件
提供API密钥的添加、编辑、删除和管理功能
"""
import os
import time
import pytz
from flask import Flask, redirect, url_for, request, jsonify
from flask_compress import Compress
from werkzeug.middleware.proxy_fix import ProxyFix
# 导入配置
from config import SECRET_KEY
# 导入API管理服务
from core.api_manager import start_service
# 设置时区为UTC+8 (亚洲/上海),兼容Linux和Windows环境
os.environ['TZ'] = 'Asia/Shanghai'
try:
# Linux环境设置
time.tzset()
except AttributeError:
# Windows环境不支持tzset,使用pytz设置
pass
# 确保datetime使用正确的时区
default_tz = pytz.timezone('Asia/Shanghai')
# 导入路由蓝图
from routes.web import web_bp
from routes.api import api_bp
# 导入认证模块
from utils.auth import AuthManager
# 导入数据库模块
from utils.db import init_db
# 创建Flask应用
app = Flask(__name__)
# 初始化Compress
compress = Compress()
# 配置Compress
app.config['COMPRESS_MIMETYPES'] = [
'text/html', 'text/css', 'text/xml', 'application/json',
'application/javascript', 'text/javascript', 'text/plain'
]
app.config['COMPRESS_LEVEL'] = 6 # gzip压缩级别 (1-9)
app.config['COMPRESS_MIN_SIZE'] = 500 # 最小压缩尺寸(字节)
app.config['COMPRESS_ALGORITHM'] = 'br,gzip' # 优先使用brotli,然后是gzip
# 应用压缩
compress.init_app(app)
# 应用ProxyFix中间件,使应用能够获取用户真实IP
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1)
app.secret_key = SECRET_KEY
# 设置静态文件缓存控制
@app.after_request
def add_cache_headers(response):
"""为静态资源添加缓存控制头"""
if request.path.startswith('/static/'):
# 设置缓存时间 - CSS、JS和图片缓存1年
max_age = 31536000 # 1年的秒数
# 根据文件类型设置不同的缓存策略
if request.path.endswith(('.css', '.js')):
# CSS和JS文件缓存1年
response.headers['Cache-Control'] = f'public, max-age={max_age}'
elif request.path.endswith(('.png', '.jpg', '.jpeg', '.gif', '.ico', '.svg')):
# 图片文件缓存1年
response.headers['Cache-Control'] = f'public, max-age={max_age}'
else:
# 其他静态文件缓存1周
response.headers['Cache-Control'] = 'public, max-age=604800'
# 添加其他有用的缓存头
response.headers['Vary'] = 'Accept-Encoding'
return response
# 认证中间件 - 验证所有请求
@app.before_request
def authenticate():
"""请求拦截器 - 验证所有需要认证的请求"""
# 登录和静态资源路径不需要验证
if request.path == '/login' or request.path.startswith('/static/'):
return
# 从Cookie中获取令牌
token = request.cookies.get('auth_token')
# 验证令牌
if not AuthManager.verify_token(token):
# 如果是AJAX请求,返回401状态码
if request.headers.get('X-Requested-With') == 'XMLHttpRequest' or request.path.startswith('/api/'):
return jsonify({"success": False, "error": "未授权访问"}), 401
# 否则重定向到登录页面
return redirect(url_for('web.login'))
# 注册蓝图
app.register_blueprint(web_bp)
app.register_blueprint(api_bp)
# 在应用启动时初始化数据库
with app.app_context():
init_db()
# 入口点
if __name__ == '__main__':
# 启动API管理服务
api_service_threads = start_service()
# 应用启动
app.run(debug=True, host='0.0.0.0', port=7860)