diff --git a/middleware/jsrt/fetch.go b/middleware/jsrt/fetch.go index bffe71345..1b79b9936 100644 --- a/middleware/jsrt/fetch.go +++ b/middleware/jsrt/fetch.go @@ -1,6 +1,7 @@ package jsrt import ( + "bytes" "context" "encoding/json" "fmt" @@ -14,16 +15,15 @@ type JSFetchRequest struct { Method string `json:"method"` URL string `json:"url"` Headers map[string]string `json:"headers"` - Body string `json:"body"` + Body any `json:"body"` Timeout int `json:"timeout"` } type JSFetchResponse struct { - Status int `json:"status"` - StatusText string `json:"statusText"` - Headers map[string]string `json:"headers"` - Body string `json:"body"` - OK bool `json:"ok"` + Status int `json:"status"` + Headers map[string]string `json:"headers"` + Body string `json:"body"` + Error string `json:"error,omitempty"` } func (p *JSRuntimePool) fetch(url string, options ...any) *JSFetchResponse { @@ -54,17 +54,7 @@ func (p *JSRuntimePool) fetch(url string, options ...any) *JSFetchResponse { } if body, exists := optMap["body"]; exists { - switch v := body.(type) { - case string: - req.Body = v - case map[string]any: - if bodyBytes, err := json.Marshal(v); err == nil { - req.Body = string(bodyBytes) - req.Headers["Content-Type"] = "application/json" - } - default: - req.Body = fmt.Sprintf("%v", body) - } + req.Body = body } if timeout, exists := optMap["timeout"]; exists { @@ -77,18 +67,27 @@ func (p *JSRuntimePool) fetch(url string, options ...any) *JSFetchResponse { // 创建HTTP请求 var bodyReader io.Reader - if req.Body != "" { - bodyReader = strings.NewReader(req.Body) + switch body := req.Body.(type) { + case string: + bodyReader = strings.NewReader(body) + case []byte: + bodyReader = bytes.NewReader(body) + case nil: + bodyReader = nil + default: + bodyBytes, err := json.Marshal(body) + if err != nil { + return &JSFetchResponse{ + Error: fmt.Sprintf("Failed to marshal body: %v", err), + } + } + bodyReader = bytes.NewReader(bodyBytes) } httpReq, err := http.NewRequest(req.Method, req.URL, bodyReader) if err != nil { return &JSFetchResponse{ - Status: 0, - StatusText: err.Error(), - Headers: make(map[string]string), - Body: "", - OK: false, + Error: err.Error(), } } @@ -110,13 +109,7 @@ func (p *JSRuntimePool) fetch(url string, options ...any) *JSFetchResponse { // 执行请求 resp, err := p.httpClient.Do(httpReq) if err != nil { - return &JSFetchResponse{ - Status: 0, - StatusText: err.Error(), - Headers: make(map[string]string), - Body: "", - OK: false, - } + return &JSFetchResponse{} } defer resp.Body.Close() @@ -124,11 +117,7 @@ func (p *JSRuntimePool) fetch(url string, options ...any) *JSFetchResponse { bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return &JSFetchResponse{ - Status: resp.StatusCode, - StatusText: resp.Status, - Headers: make(map[string]string), - Body: "", - OK: resp.StatusCode >= 200 && resp.StatusCode < 300, + Status: resp.StatusCode, } } @@ -141,10 +130,8 @@ func (p *JSRuntimePool) fetch(url string, options ...any) *JSFetchResponse { } return &JSFetchResponse{ - Status: resp.StatusCode, - StatusText: resp.Status, - Headers: headers, - Body: string(bodyBytes), - OK: resp.StatusCode >= 200 && resp.StatusCode < 300, + Status: resp.StatusCode, + Headers: headers, + Body: string(bodyBytes), } } diff --git a/middleware/jsrt/jsrt.go b/middleware/jsrt/jsrt.go index 37f65829d..b14d14dbe 100644 --- a/middleware/jsrt/jsrt.go +++ b/middleware/jsrt/jsrt.go @@ -146,6 +146,7 @@ func (p *JSRuntimePool) setupGlobals(vm *goja.Runtime) { // 数据库 vm.Set("db", &JSDatabase{db: model.DB}) + vm.Set("logdb", &JSDatabase{db: model.LOG_DB}) // 定时器 vm.Set("setTimeout", func(fn func(), delay int) { diff --git a/scripts/pre_process.js b/scripts/pre_process.js index 7ab6e71ea..72047f9b0 100644 --- a/scripts/pre_process.js +++ b/scripts/pre_process.js @@ -30,34 +30,137 @@ function preProcessRequest(ctx) { // } // 例子:修改请求 - if (ctx.URL.includes("/v1/chat/completions")) { - try { - var bodyObj = ctx.Body; + // if (ctx.URL.includes("/v1/chat/completions")) { + // try { + // var bodyObj = ctx.Body; - let firstMsg = { - role: "user", - content: "今天天气怎么样" - }; - bodyObj.messages[0] = firstMsg; - console.log("Modified first message:", JSON.stringify(firstMsg)); - console.log("Modified body:", JSON.stringify(bodyObj)); + // let firstMsg = { // 需要新建一个对象,不能修改原有对象 + // role: "user", + // content: "今天天气怎么样" + // }; + // bodyObj.messages[0] = firstMsg; + // console.log("Modified first message:", JSON.stringify(firstMsg)); + // console.log("Modified body:", JSON.stringify(bodyObj)); - return { - body: bodyObj, - headers: { - ...ctx.Headers, - "X-Modified-Body": "true" - } - }; - } catch (e) { - console.error("Failed to modify request body:", { - message: e.message, - stack: e.stack, - bodyType: typeof ctx.Body, - url: ctx.URL - }); - } - } + // return { + // body: bodyObj, + // headers: { + // ...ctx.Headers, + // "X-Modified-Body": "true" + // } + // }; + // } catch (e) { + // console.error("Failed to modify request body:", { + // message: e.message, + // stack: e.stack, + // bodyType: typeof ctx.Body, + // url: ctx.URL + // }); + // } + // } + + // // 例子:读取最近一条日志,新增 jsrt 日志,并输出日志总数 + // if (ctx.URL) { + // 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 预处理中间件执行 - " + ctx.URL + " - " + new Date().toISOString(); + + // var insertResult = logdb.Exec( + // "INSERT INTO logs (user_id, username, created_at, type, content) VALUES (?, ?, ?, ?, ?)", + // ctx.UserID || 0, + // ctx.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: ctx.URL + // }); + // } + // } + + // // 例子:使用 fetch 调用外部 API + // if (ctx.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 (?, ?, ?, ?, ?)", + // ctx.UserID || 0, + // ctx.Username || "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: ctx.URL + // }); + // } + // } return undefined; // 跳过处理,继续执行下一个中间件或路由 }