File size: 3,750 Bytes
ef8784d
 
 
 
 
 
 
 
 
 
 
 
 
 
99fc92f
 
 
ef8784d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99fc92f
 
ef8784d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99fc92f
 
 
 
ef8784d
 
99fc92f
 
 
ef8784d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"""

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)