-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathwebServer.py
More file actions
executable file
·166 lines (136 loc) · 5.32 KB
/
Copy pathwebServer.py
File metadata and controls
executable file
·166 lines (136 loc) · 5.32 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import flask
from flask import request
from __init__ import *
from main import process
DEFAULT_JSON_CORS_ORIGINS = {
"https://peer.as",
"https://www.peer.as",
"https://cn.peer.as",
}
def is_version_acceptable(user_agent):
"""
判断客户端版本是否符合要求
:param user_agent:
:return: 0 不符合要求 1 最新版本 2 符合要求但可升级的版本
"""
# 正则表达式用于匹配版本号
user_agent = user_agent or ""
match = re.search(r"NextTrace v(\d+\.\d+\.\d+)", user_agent)
if match:
user_version = match.group(1)
try:
acc = version.parse(accept_version)
lat = version.parse(latest_version)
usr = version.parse(user_version) # compare by numeric core only
if usr >= acc:
if usr >= lat:
return 1
else:
return 2
else:
return 0
except ValueError:
return 0
else:
match = re.search(r"NextTrace (\d+\.\d+\.\d+)", user_agent) # 给 HomeBrew 版本的不规范版本擦屁股
if match:
user_version = match.group(1)
try:
acc = version.parse(accept_version)
lat = version.parse(latest_version)
usr = version.parse(user_version)
if usr >= acc:
if usr >= lat:
return 1
else:
return 2
else:
return 0
except ValueError:
return 0
else:
# 如果无法解析版本号,视为不符合要求
return 0
def _json_cors_origins():
raw = os.environ.get("TRACEMAP_JSON_CORS_ORIGINS")
if raw is None:
return DEFAULT_JSON_CORS_ORIGINS
return {item.strip() for item in raw.split(",") if item.strip()}
def _add_json_cors(resp):
origin = request.headers.get("Origin", "").strip()
if origin and origin in _json_cors_origins():
resp.headers["Access-Control-Allow-Origin"] = origin
resp.vary.add("Origin")
resp.headers["Access-Control-Allow-Methods"] = "GET, OPTIONS"
resp.headers["Access-Control-Allow-Headers"] = "Content-Type"
resp.headers["Access-Control-Max-Age"] = "86400"
return resp
def _json_filename(filename):
base = os.path.basename(filename)
if base.endswith(".html"):
base = base[:-5]
if not base.endswith(".json"):
base += ".json"
return base
def trace_json(filename):
if request.method == "OPTIONS":
return _add_json_cors(flask.Response(status=204))
resp = flask.send_from_directory("html", _json_filename(filename), mimetype="application/json")
resp.headers["Cache-Control"] = "public, max-age=86400"
return _add_json_cors(resp)
def trace_asset(filename):
if filename.endswith(".json") or request.method == "OPTIONS":
return trace_json(filename)
return flask.send_from_directory('html', filename)
def html(filename):
if filename.endswith(".json"):
return trace_json(filename)
return flask.send_from_directory('html', filename)
def favicon():
return flask.send_file('favicon.ico', mimetype='image/vnd.microsoft.icon')
def api():
data = json.loads(request.data.decode("utf-8"))
uName = str(uuid.uuid5(uuid.NAMESPACE_DNS, request.get_data().decode()))
json_str = json.dumps(data, ensure_ascii=False)
data = json.loads(json_str)
with open('log/' + uName + '.json', 'w', encoding='utf-8') as f:
f.write(json_str)
logging.info("Saved log to log/" + uName + ".json")
try:
filename = process(data, filename=uName + '.html')
logging.info("Saved html to " + filename)
except Exception as e:
logging.error("uuid:", uName)
logging.error(e)
print(traceback.format_exc())
return "", 500
# 根据UA判断版本
version_result = is_version_acceptable(request.headers.get('User-Agent'))
if version_result == 1:
return filename, 200
elif version_result == 2:
return filename, 200
else:
return filename + '\n' + '您正在使用的版本,将在一个月内停止支持,请及时升级您的客户端', 406
class WebServer:
def __init__(self):
self.app = flask.Flask(__name__)
if 'GUNICORN_CMD_ARGS' in os.environ:
gunicorn_logger = logging.getLogger('gunicorn.error')
self.app.logger.handlers = gunicorn_logger.handlers
self.app.logger.setLevel(gunicorn_logger.level)
else:
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
self.app.config['JSON_AS_ASCII'] = False
self.urlPrefix = "http://localhost:8888/html/"
self.app.route('/api', methods=['post'])(api)
self.app.route('/html/<filename>', methods=['get'])(html)
self.app.route('/json/<filename>', methods=['GET', 'OPTIONS'])(trace_json)
self.app.route('/tracemap/<filename>', methods=['GET', 'OPTIONS'])(trace_asset)
self.app.route('/favicon.ico', methods=['get'])(favicon)
def run(self, host="0.0.0.0", port=18888, debug=True):
self.app.run(host=host, port=port, debug=debug)
server = WebServer()
APP = server.app
if __name__ == '__main__':
server.run()