diff --git a/docs/jsrt/JS_RUNTIME.md b/docs/jsrt/JS_RUNTIME.md index 737620786..712bc937a 100644 --- a/docs/jsrt/JS_RUNTIME.md +++ b/docs/jsrt/JS_RUNTIME.md @@ -71,90 +71,147 @@ var result = db.Exec("UPDATE users SET last_login = NOW() WHERE id = ?", 123); ## 使用示例 -### 请求限流 +```js +// 例子:基于数据库的速率限制 +if (req.url.includes("/v1/chat/completions")) { + try { + // Check recent requests from this IP + var recentRequests = db.query( + "SELECT COUNT(*) as count FROM logs WHERE created_at > ? AND ip = ?", + Math.floor(Date.now() / 1000) - 60, // last minute + req.remoteIP + ); + if (recentRequests && recentRequests.length > 0 && recentRequests[0].count > 10) { + console.log("速率限制 IP:", req.remoteIP); + return { + block: true, + statusCode: 429, + message: "超过速率限制" + }; + } + } catch (e) { + console.error("Ratelimit 数据库错误:", e); + } +} -```javascript -function preProcessRequest(ctx) { - // 基于 IP 的简单限流 - var recentRequests = db.Query( - "SELECT COUNT(*) as count FROM request_logs WHERE ip = ? AND timestamp > ?", - ctx.remoteIP, - new Date(Date.now() - 60000).toISOString() // 最近1分钟 - ); - - if (recentRequests[0].count > 100) { - return { - block: true, - statusCode: 429, - message: "Too many requests" + +// 例子:修改请求 +if (req.url.includes("/chat/completions")) { + try { + var bodyObj = req.body; + let firstMsg = { // 需要新建一个对象,不能修改原有对象 + role: "user", + content: "喵呜🐱~嘻嘻" }; - } - - // 记录请求 - db.Exec( - "INSERT INTO request_logs (ip, url, timestamp) VALUES (?, ?, ?)", - ctx.remoteIP, ctx.url, new Date().toISOString() - ); -} -``` - -### 请求修改 - -```javascript -function preProcessRequest(ctx) { - if (ctx.method === "POST" && ctx.body) { - try { - var bodyObj = JSON.parse(ctx.body); - - // 添加默认参数 - if (!bodyObj.temperature) { - bodyObj.temperature = 0.7; + bodyObj.messages[0] = firstMsg; + console.log("Modified first message:", JSON.stringify(firstMsg)); + console.log("Modified body:", JSON.stringify(bodyObj)); + return { + body: bodyObj, + headers: { + ...req.headers, + "X-Modified-Body": "true" } - - // 添加用户标识 - bodyObj._userId = ctx.extra.userId; - - return { - body: JSON.stringify(bodyObj) - }; - } catch (e) { - console.error("Failed to parse request body:", e); - } + }; + } catch (e) { + console.error("Failed to modify request body:", { + message: e.message, + stack: e.stack, + bodyType: typeof req.body, + url: req.url + }); } } -``` -### 响应增强 -```javascript -function postProcessResponse(ctx, response) { - if (response.statusCode === 200 && ctx.url.includes("/v1/chat/completions")) { - try { - var bodyObj = JSON.parse(response.body); - - // 添加自定义元数据 - bodyObj.metadata = { - processedAt: new Date().toISOString(), - version: "1.0.0" - }; - - // 记录成功的对话 - db.Exec( - "INSERT INTO chat_logs (user_ip, model, tokens, timestamp) VALUES (?, ?, ?, ?)", - ctx.remoteIP, bodyObj.model, bodyObj.usage?.total_tokens || 0, new Date().toISOString() - ); - - return { - statusCode: response.statusCode, - headers: response.headers, - body: JSON.stringify(bodyObj) - }; - } catch (e) { - console.error("Failed to process chat completion response:", e); - } +// 例子:读取最近一条日志,新增 jsrt 日志,并输出日志总数 +try { + // 1. 读取最近一条日志 + var recentLogs = logdb.query( + "SELECT id, user_id, username, content, created_at FROM logs ORDER BY id DESC LIMIT 1" + ); + var recentLog = null; + if (recentLogs && recentLogs.length > 0) { + recentLog = recentLogs[0]; + console.log("最近一条日志:", JSON.stringify(recentLog)); + } + // 2. 新增一条 jsrt 日志 + var currentTimestamp = Math.floor(Date.now() / 1000); + var jsrtLogContent = "JSRT 预处理中间件执行 - " + req.URL + " - " + new Date().toISOString(); + var insertResult = logdb.exec( + "INSERT INTO logs (user_id, username, created_at, type, content) VALUES (?, ?, ?, ?, ?)", + req.UserID || 0, + req.Username || "jsrt-system", + currentTimestamp, + 4, // LogTypeSystem + jsrtLogContent + ); + if (insertResult.error) { + console.error("插入 JSRT 日志失败:", insertResult.error); + } else { + console.log("成功插入 JSRT 日志,影响行数:", insertResult.rowsAffected); + } + // 3. 输出日志总数 + var totalLogsResult = logdb.query("SELECT COUNT(*) as total FROM logs"); + var totalLogs = 0; + if (totalLogsResult && totalLogsResult.length > 0) { + totalLogs = totalLogsResult[0].total; + } + console.log("当前日志总数:", totalLogs); + console.log("JSRT 日志管理示例执行完成"); +} catch (e) { + console.error("JSRT 日志管理示例执行失败:", { + message: e.message, + stack: e.stack, + url: req.URL + }); +} + + +// 例子:使用 fetch 调用外部 API +if (req.url.includes("/api/uptime/status")) { + try { + // 使用 httpbin.org/ip 测试 fetch 功能 + var response = fetch("https://httpbin.org/ip", { + method: "GET", + timeout: 5, // 5秒超时 + headers: { + "User-Agent": "OneAPI-JSRT/1.0" + } + }); + if (response.Error.length === 0) { + // 解析响应体 + var ipData = JSON.parse(response.Body); + // 可以根据获取到的 IP 信息进行后续处理 + if (ipData.origin) { + console.log("外部 IP 地址:", ipData.origin); + // 示例:记录 IP 信息到数据库 + var currentTimestamp = Math.floor(Date.now() / 1000); + var logContent = "Fetch 示例 - 外部 IP: " + ipData.origin + " - " + new Date().toISOString(); + var insertResult = logdb.exec( + "INSERT INTO logs (user_id, username, created_at, type, content) VALUES (?, ?, ?, ?, ?)", + 0, + "jsrt-fetch", + currentTimestamp, + 4, // LogTypeSystem + logContent + ); + if (insertResult.error) { + console.error("记录 IP 信息失败:", insertResult.error); + } else { + console.log("成功记录 IP 信息到数据库"); + } + } + } else { + console.error("Fetch 失败 ", response.Status, " ", response.Error); + } + } catch (e) { + console.error("Fetch 失败:", { + message: e.message, + stack: e.stack, + url: req.url + }); } - - return response; } ```