tkserver 1.7.9 → 1.7.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/index.js +30 -1
- package/mongo.js +18 -2
- package/package.json +2 -2
- package/server.js +86 -1
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ tkserver
|
|
|
19
19
|
| `MONGODB_URI` | MongoDB 数据库连接字符串,不传则使用 lokijs | `null` |
|
|
20
20
|
| `MONGO_URL` | MongoDB 数据库连接字符串,不传则使用 lokijs | `null` |
|
|
21
21
|
| `TWIKOO_DATA` | lokijs 数据库存储路径 | `./data` |
|
|
22
|
+
| `TWIKOO_HOST` | 自定义监听的主机名或IP地址(例如 0.0.0.0 或 127.0.0.1),设置该值则会忽略 TWIKOO_LOCALHOST_ONLY,默认值为 null 但实际行为会回退到 `::` | `null` |
|
|
22
23
|
| `TWIKOO_PORT` | 端口号 | `8080` |
|
|
23
24
|
| `TWIKOO_THROTTLE` | IP 请求限流,当同一 IP 短时间内请求次数超过阈值将对该 IP 返回错误 | `250` |
|
|
24
25
|
| `TWIKOO_LOCALHOST_ONLY` | 为`true`时只监听本地请求,使得 nginx 等服务器反代之后不暴露原始端口 | `null` |
|
package/index.js
CHANGED
|
@@ -69,6 +69,7 @@ const TWIKOO_REQ_TIMES_CLEAR_TIME = parseInt(process.env.TWIKOO_REQ_TIMES_CLEAR_
|
|
|
69
69
|
let db = null
|
|
70
70
|
let config
|
|
71
71
|
let requestTimes = {}
|
|
72
|
+
let requestTimesTimer = null
|
|
72
73
|
|
|
73
74
|
connectToDatabase()
|
|
74
75
|
|
|
@@ -1065,8 +1066,36 @@ function getIp (request) {
|
|
|
1065
1066
|
return getUserIP(request)
|
|
1066
1067
|
}
|
|
1067
1068
|
|
|
1069
|
+
async function closeDatabase () {
|
|
1070
|
+
if (!db) return
|
|
1071
|
+
try {
|
|
1072
|
+
await new Promise((resolve, reject) => {
|
|
1073
|
+
db.saveDatabase((err) => {
|
|
1074
|
+
if (err) {
|
|
1075
|
+
reject(err)
|
|
1076
|
+
} else {
|
|
1077
|
+
resolve()
|
|
1078
|
+
}
|
|
1079
|
+
})
|
|
1080
|
+
})
|
|
1081
|
+
} finally {
|
|
1082
|
+
db.close()
|
|
1083
|
+
db = null
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
async function shutdown () {
|
|
1088
|
+
if (requestTimesTimer) {
|
|
1089
|
+
clearInterval(requestTimesTimer)
|
|
1090
|
+
requestTimesTimer = null
|
|
1091
|
+
}
|
|
1092
|
+
await closeDatabase()
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1068
1095
|
function clearRequestTimes () {
|
|
1069
1096
|
requestTimes = {}
|
|
1070
1097
|
}
|
|
1071
1098
|
|
|
1072
|
-
setInterval(clearRequestTimes, TWIKOO_REQ_TIMES_CLEAR_TIME)
|
|
1099
|
+
requestTimesTimer = setInterval(clearRequestTimes, TWIKOO_REQ_TIMES_CLEAR_TIME)
|
|
1100
|
+
|
|
1101
|
+
module.exports.shutdown = shutdown
|
package/mongo.js
CHANGED
|
@@ -66,6 +66,8 @@ const TWIKOO_REQ_TIMES_CLEAR_TIME = parseInt(process.env.TWIKOO_REQ_TIMES_CLEAR_
|
|
|
66
66
|
let db = null
|
|
67
67
|
let config
|
|
68
68
|
let requestTimes = {}
|
|
69
|
+
let client = null
|
|
70
|
+
let requestTimesTimer = null
|
|
69
71
|
|
|
70
72
|
module.exports = async (request, response) => {
|
|
71
73
|
let accessToken
|
|
@@ -225,7 +227,7 @@ async function connectToDatabase (uri) {
|
|
|
225
227
|
if (!uri) throw new Error('未设置环境变量 MONGODB_URI | MONGO_URL')
|
|
226
228
|
// If no connection is cached, create a new one
|
|
227
229
|
logger.info('Connecting to database...')
|
|
228
|
-
|
|
230
|
+
client = await MongoClient.connect(uri, {})
|
|
229
231
|
// Select the database through the connection,
|
|
230
232
|
// using the database path of the connection string
|
|
231
233
|
const dbName = (new URL(uri)).pathname.substring(1) || 'twikoo'
|
|
@@ -1037,8 +1039,22 @@ function getIp (request) {
|
|
|
1037
1039
|
return getUserIP(request)
|
|
1038
1040
|
}
|
|
1039
1041
|
|
|
1042
|
+
async function shutdown () {
|
|
1043
|
+
if (requestTimesTimer) {
|
|
1044
|
+
clearInterval(requestTimesTimer)
|
|
1045
|
+
requestTimesTimer = null
|
|
1046
|
+
}
|
|
1047
|
+
if (client) {
|
|
1048
|
+
await client.close()
|
|
1049
|
+
client = null
|
|
1050
|
+
db = null
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1040
1054
|
function clearRequestTimes () {
|
|
1041
1055
|
requestTimes = {}
|
|
1042
1056
|
}
|
|
1043
1057
|
|
|
1044
|
-
setInterval(clearRequestTimes, TWIKOO_REQ_TIMES_CLEAR_TIME)
|
|
1058
|
+
requestTimesTimer = setInterval(clearRequestTimes, TWIKOO_REQ_TIMES_CLEAR_TIME)
|
|
1059
|
+
|
|
1060
|
+
module.exports.shutdown = shutdown
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tkserver",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.10",
|
|
4
4
|
"description": "A simple comment system.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"twikoo",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"get-user-ip": "^1.0.1",
|
|
32
32
|
"lokijs": "^1.5.12",
|
|
33
33
|
"mongodb": "^6.3.0",
|
|
34
|
-
"twikoo-func": "1.7.
|
|
34
|
+
"twikoo-func": "1.7.10",
|
|
35
35
|
"uuid": "^8.3.2"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/server.js
CHANGED
|
@@ -6,8 +6,20 @@ const logger = require('twikoo-func/utils/logger')
|
|
|
6
6
|
const dbUrl = process.env.MONGODB_URI || process.env.MONGO_URL || null
|
|
7
7
|
const twikoo = dbUrl ? require('./mongo') : require('./index')
|
|
8
8
|
const server = http.createServer()
|
|
9
|
+
const sockets = new Set()
|
|
10
|
+
const TWIKOO_SHUTDOWN_TIMEOUT = parseInt(process.env.TWIKOO_SHUTDOWN_TIMEOUT) || 5000
|
|
11
|
+
let isShuttingDown = false
|
|
12
|
+
let shuttingDownPromise = null
|
|
9
13
|
|
|
10
14
|
server.on('request', async function (request, response) {
|
|
15
|
+
if (isShuttingDown) {
|
|
16
|
+
response.writeHead(503, {
|
|
17
|
+
Connection: 'close',
|
|
18
|
+
'Content-Type': 'application/json'
|
|
19
|
+
})
|
|
20
|
+
response.end(JSON.stringify({ code: 503, message: 'Twikoo server is shutting down' }))
|
|
21
|
+
return
|
|
22
|
+
}
|
|
11
23
|
try {
|
|
12
24
|
const buffers = []
|
|
13
25
|
for await (const chunk of request) {
|
|
@@ -31,10 +43,83 @@ server.on('request', async function (request, response) {
|
|
|
31
43
|
return await twikoo(request, response)
|
|
32
44
|
})
|
|
33
45
|
|
|
46
|
+
server.on('connection', (socket) => {
|
|
47
|
+
sockets.add(socket)
|
|
48
|
+
socket.on('close', () => sockets.delete(socket))
|
|
49
|
+
})
|
|
50
|
+
|
|
34
51
|
const port = parseInt(process.env.TWIKOO_PORT) || 8080
|
|
35
|
-
const host = process.env.TWIKOO_LOCALHOST_ONLY === 'true' ? 'localhost' : '::'
|
|
52
|
+
const host = process.env.TWIKOO_HOST || (process.env.TWIKOO_LOCALHOST_ONLY === 'true' ? 'localhost' : '::')
|
|
36
53
|
|
|
37
54
|
server.listen(port, host, function () {
|
|
38
55
|
logger.info(`Twikoo is using ${dbUrl ? 'mongo' : 'loki'} database`)
|
|
39
56
|
logger.info(`Twikoo function started on host ${host} port ${port}`)
|
|
40
57
|
})
|
|
58
|
+
|
|
59
|
+
function closeServer () {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
server.close((err) => {
|
|
62
|
+
if (err) {
|
|
63
|
+
reject(err)
|
|
64
|
+
} else {
|
|
65
|
+
resolve()
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function destroySockets () {
|
|
72
|
+
for (const socket of sockets) {
|
|
73
|
+
socket.destroy()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function shutdownWithTimeout () {
|
|
78
|
+
let timeoutId
|
|
79
|
+
const closeTask = closeServer()
|
|
80
|
+
const timeoutTask = new Promise((resolve) => {
|
|
81
|
+
timeoutId = setTimeout(() => {
|
|
82
|
+
logger.warn(`Twikoo server shutdown timed out after ${TWIKOO_SHUTDOWN_TIMEOUT}ms, destroying open connections`)
|
|
83
|
+
destroySockets()
|
|
84
|
+
resolve()
|
|
85
|
+
}, TWIKOO_SHUTDOWN_TIMEOUT)
|
|
86
|
+
})
|
|
87
|
+
await Promise.race([closeTask, timeoutTask])
|
|
88
|
+
clearTimeout(timeoutId)
|
|
89
|
+
await closeTask
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function runShutdown (signal) {
|
|
93
|
+
isShuttingDown = true
|
|
94
|
+
logger.info(`Received ${signal}, shutting down Twikoo server...`)
|
|
95
|
+
try {
|
|
96
|
+
await shutdownWithTimeout()
|
|
97
|
+
} catch (e) {
|
|
98
|
+
logger.error('Twikoo HTTP server shutdown failed:', e)
|
|
99
|
+
} finally {
|
|
100
|
+
if (typeof twikoo.shutdown === 'function') {
|
|
101
|
+
await twikoo.shutdown()
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
logger.info('Twikoo server stopped')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function shutdown (signal) {
|
|
108
|
+
if (!shuttingDownPromise) {
|
|
109
|
+
shuttingDownPromise = runShutdown(signal)
|
|
110
|
+
}
|
|
111
|
+
return await shuttingDownPromise
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function handleSignal (signal) {
|
|
115
|
+
try {
|
|
116
|
+
await shutdown(signal)
|
|
117
|
+
process.exitCode = 0
|
|
118
|
+
} catch (e) {
|
|
119
|
+
logger.error('Twikoo server shutdown failed:', e)
|
|
120
|
+
process.exitCode = 1
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
process.on('SIGTERM', () => handleSignal('SIGTERM'))
|
|
125
|
+
process.on('SIGINT', () => handleSignal('SIGINT'))
|