@less-is-more/less-js 1.5.0-9 → 1.5.1-1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@less-is-more/less-js",
3
- "version": "1.5.0-9",
3
+ "version": "1.5.1-1",
4
4
  "description": "Fast develop kit for nodejs",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/cache.js CHANGED
@@ -103,10 +103,14 @@ module.exports = class Cache {
103
103
  } else {
104
104
  console.log("Found cache" + (hasLocal ? " local" : ""), fullKey);
105
105
  savedData = Cache._unzip(savedData);
106
- // 优先转成json
107
- try {
108
- return JSON.parse(savedData);
109
- } catch (e) {
106
+ if (typeof savedData === "string") {
107
+ // 优先转成json
108
+ try {
109
+ return JSON.parse(savedData);
110
+ } catch (e) {
111
+ return savedData;
112
+ }
113
+ } else {
110
114
  return savedData;
111
115
  }
112
116
  }
@@ -118,16 +122,19 @@ module.exports = class Cache {
118
122
  }
119
123
 
120
124
  static _unzip(content) {
121
- // 判断content是否是buffer
122
- let text = "";
123
- const buffer = Buffer.from(content, "base64");
124
- // 判断是否gzip
125
- if (buffer.length > 2 && buffer[0] === 0x1f && buffer[1] === 0x8b) {
126
- text = zlib.gunzipSync(buffer).toString();
125
+ if (typeof content === "string") {
126
+ let text = "";
127
+ const buffer = Buffer.from(content, "base64");
128
+ // 判断是否gzip
129
+ if (buffer.length > 2 && buffer[0] === 0x1f && buffer[1] === 0x8b) {
130
+ text = zlib.gunzipSync(buffer).toString();
131
+ } else {
132
+ text = content;
133
+ }
134
+ return text;
127
135
  } else {
128
- text = content;
136
+ return content;
129
137
  }
130
- return text;
131
138
  }
132
139
 
133
140
  static _needZip(text, zip) {
package/src/nas.js CHANGED
@@ -115,8 +115,6 @@ class Nas {
115
115
  return valueStr;
116
116
  }
117
117
  } else {
118
- // 文件已过期,删除文件
119
- Nas._deleteCacheFile(key);
120
118
  return null;
121
119
  }
122
120
  }
@@ -141,11 +139,25 @@ class Nas {
141
139
  const filePath = Nas._getFilePath(key);
142
140
 
143
141
  try {
142
+ // 创建临时文件名,避免写入过程中的并发问题
143
+ const timestamp = Date.now();
144
+ const randomSuffix = Math.random().toFixed(4) * 10000;
145
+ const tempFilePath = `${filePath}.tmp.${timestamp}.${randomSuffix}`;
144
146
  // 写入过期时间戳和值,用换行符分隔
145
147
  const fileContent = `${expireTime}\n${content}`;
146
- fs.writeFileSync(filePath, fileContent, "utf8");
148
+ fs.writeFileSync(tempFilePath, fileContent, "utf8");
149
+ // 原子性地替换原文件
150
+ fs.renameSync(tempFilePath, filePath);
147
151
  } catch (e) {
148
152
  console.error("保存缓存文件失败:", filePath, e);
153
+ // 如果临时文件创建失败,清理临时文件
154
+ try {
155
+ if (fs.existsSync(tempFilePath)) {
156
+ fs.unlinkSync(tempFilePath);
157
+ }
158
+ } catch (cleanupError) {
159
+ // 忽略清理错误
160
+ }
149
161
  }
150
162
  }
151
163
 
@@ -186,23 +198,25 @@ class Nas {
186
198
  for (const file of files) {
187
199
  if (file.endsWith(".cache")) {
188
200
  const filePath = path.join(cacheDir, file);
189
- // 检查文件是否过期,如果过期则删除
201
+ // 检查文件是否过期超过一分钟,如果超过则删除
190
202
  try {
191
- const content = fs.readFileSync(filePath, "utf8");
192
- const lines = content.split("\n");
203
+ if (fs.existsSync(filePath)) {
204
+ const content = fs.readFileSync(filePath, "utf8");
205
+ const lines = content.split("\n");
193
206
 
194
- if (lines.length >= 1) {
195
- const expireTimeString = lines[0];
196
- const expireTime = parseInt(expireTimeString);
207
+ if (lines.length >= 1) {
208
+ const expireTimeString = lines[0];
209
+ const expireTime = parseInt(expireTimeString);
197
210
 
198
- if (
199
- !isNaN(expireTime) &&
200
- expireTime !== -1 &&
201
- Date.now() > expireTime
202
- ) {
203
- console.log("删除过期缓存文件:", filePath);
204
- // 文件已过期,删除文件
205
- fs.unlinkSync(filePath);
211
+ if (
212
+ !isNaN(expireTime) &&
213
+ expireTime !== -1 &&
214
+ // 仅删除过期超过一分钟的文件
215
+ Date.now() > expireTime + 60 * 1000
216
+ ) {
217
+ console.log("删除过期缓存文件:", filePath);
218
+ fs.unlinkSync(filePath);
219
+ }
206
220
  }
207
221
  }
208
222
  } catch (e) {
@@ -268,8 +282,6 @@ class Nas {
268
282
  const remainingTime = Math.floor((expireTime - Date.now()) / 1000);
269
283
  return Math.max(0, remainingTime); // 确保返回非负值
270
284
  } else {
271
- // 文件已过期,删除文件
272
- Nas._deleteCacheFile(key);
273
285
  return -1;
274
286
  }
275
287
  }
package/src/router.js CHANGED
@@ -71,6 +71,7 @@ module.exports = class Router {
71
71
  // 兼容非阿里云
72
72
  await this._handleParams(req);
73
73
  console.log(
74
+ req.sourceIp,
74
75
  "p:",
75
76
  req.method,
76
77
  req.path,
@@ -184,6 +185,11 @@ module.exports = class Router {
184
185
  delete req.params[0];
185
186
  }
186
187
 
188
+ // 处理IP
189
+ if (Param.isBlank(req.sourceIp)) {
190
+ req.sourceIp = this._getRealIP(req);
191
+ }
192
+
187
193
  if (!Param.isBlank(req.queries)) {
188
194
  Object.keys(req.queries).forEach((n) => (req.params[n] = req.queries[n]));
189
195
  }
@@ -274,4 +280,52 @@ module.exports = class Router {
274
280
  static useDefaultFormat(isUse) {
275
281
  this.#defaultFormat = isUse;
276
282
  }
283
+
284
+ /**
285
+ * 获取真实IP地址
286
+ * @param {object} req 请求对象
287
+ * @returns {string} IP地址
288
+ */
289
+ static _getRealIP(req) {
290
+ // 检查常用的HTTP头字段来获取原始IP地址
291
+ const forwardedIP =
292
+ req.headers["x-forwarded-for"] ||
293
+ req.headers["x-real-ip"] ||
294
+ req.headers["x-client-ip"] ||
295
+ req.headers["x-cluster-client-ip"];
296
+
297
+ if (forwardedIP) {
298
+ // x-forwarded-for 可能包含多个IP地址,第一个通常是真实的客户端IP
299
+ const ipList = forwardedIP.split(",");
300
+ const clientIP = ipList[0].trim();
301
+ if (clientIP && this.isValidIP(clientIP)) {
302
+ return clientIP;
303
+ }
304
+ }
305
+
306
+ // fallback到连接级别的IP
307
+ return req.connection
308
+ ? req.connection.remoteAddress
309
+ : req.socket
310
+ ? req.socket.remoteAddress
311
+ : "";
312
+ }
313
+
314
+ /**
315
+ * 验证IP地址格式是否有效
316
+ * @param {string} ip IP地址字符串
317
+ * @returns {boolean} 是否为有效的IP地址
318
+ */
319
+ static isValidIP(ip) {
320
+ // 简单验证IP格式,支持IPv4和基本的IPv6格式
321
+ if (!ip || typeof ip !== "string") return false;
322
+
323
+ // IPv4 正则表达式
324
+ const ipv4Regex =
325
+ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
326
+ // IPv6 正则表达式(简化版)
327
+ const ipv6Regex = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;
328
+
329
+ return ipv4Regex.test(ip.trim()) || ipv6Regex.test(ip.trim());
330
+ }
277
331
  };