forked from Moonrend/ClassworksKV
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
146 lines (122 loc) · 4.29 KB
/
Copy pathapp.js
File metadata and controls
146 lines (122 loc) · 4.29 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
import "./utils/instrumentation.js";
// import createError from "http-errors";
import express from "express";
import {dirname, join} from "path";
import {fileURLToPath} from "url";
// import cookieParser from "cookie-parser";
import logger from "morgan";
import bodyParser from "body-parser";
import errorHandler from "./middleware/errorHandler.js";
import errors from "./utils/errors.js";
import kvRouter from "./routes/kv-token.js";
import appsRouter from "./routes/apps.js";
import deviceRouter from "./routes/device.js";
import deviceAuthRouter from "./routes/device-auth.js";
import accountsRouter from "./routes/accounts.js";
import autoAuthRouter from "./routes/auto-auth.js";
import {register} from "./utils/metrics.js";
import cors from "cors";
var app = express();
app.options("/{*path}", cors());
app.use(
cors({
exposedHeaders: ["ratelimit-policy", "retry-after", "ratelimit"], // 告诉浏览器这些响应头可以暴露
maxAge: 86400, // 设置OPTIONS请求的结果缓存24小时(86400秒),减少预检请求
})
);
app.disable("x-powered-by");
// 获取当前文件的目录路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// view engine setup
app.set("views", join(__dirname, "views"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
// app.use(cookieParser());
app.use(express.static(join(__dirname, "public")));
// 添加请求超时处理中间件
app.use((req, res, next) => {
// 设置默认请求超时时间为30秒
const timeout = 30000;
// 设置超时回调
const timeoutCallback = () => {
const timeoutError = errors.createError(408, "请求处理超时");
next(timeoutError);
};
// 设置超时
req.setTimeout(timeout, timeoutCallback);
// 监听响应完成事件
res.on("finish", () => {
// 如果响应已经完成,清除超时处理
req.setTimeout(0, timeoutCallback);
});
next();
});
app.get("/", (req, res) => {
res.render("index.ejs");
});
app.get("/check", (req, res) => {
res.json({
status: "success",
message: "Classworks KV is running",
time: new Date().getTime(),
});
});
// Prometheus metrics endpoint with token auth
app.get("/metrics", async (req, res) => {
try {
// 检查 token 验证
const metricsToken = process.env.METRICS_TOKEN;
if (metricsToken) {
const providedToken = req.headers.authorization?.replace('Bearer ', '') || req.query.token;
if (!providedToken || providedToken !== metricsToken) {
return res.status(401).json({
error: "Unauthorized",
message: "Valid metrics token required"
});
}
}
res.set("Content-Type", register.contentType);
res.end(await register.metrics());
} catch (err) {
res.status(500).end(err.message);
}
});
// Mount the Apps router with API rate limiting
app.use("/apps", appsRouter);
// Mount the Auto Auth router with API rate limiting
app.use("/auto-auth", autoAuthRouter);
// Mount the Device router with API rate limiting
app.use("/devices", deviceRouter);
// Mount the KV store router
app.use("/kv", kvRouter);
// Mount the Device Authorization router with API rate limiting
app.use("/auth", deviceAuthRouter);
// Mount the Accounts router with API rate limiting
app.use("/accounts", accountsRouter);
// 兜底404路由 - 处理所有未匹配的路由
app.use((req, res, next) => {
const notFoundError = errors.createError(404, `找不到路径: ${req.path}`);
next(notFoundError);
});
// 全局错误处理中间件
app.use(errorHandler);
// 全局未捕获的异常处理
process.on("uncaughtException", (error) => {
console.error("未捕获的异常:", error);
// 记录错误但不退出进程
});
// 全局未处理的Promise拒绝处理
process.on("unhandledRejection", (reason, promise) => {
console.error("未处理的Promise拒绝:", reason);
// 记录错误但不退出进程
});
// 处理 SIGTERM 信号
process.on("SIGTERM", () => {
console.log("收到 SIGTERM 信号,准备关闭服务...");
});
export default app;