Files
waf-platform/EdgeNode/internal/nodes/http_request_events_script_plus.go
2026-02-04 20:27:13 +08:00

125 lines
3.4 KiB
Go

// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build script
// +build script
package nodes
import (
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"rogchap.com/v8go"
"strings"
)
func (this *HTTPRequest) onInit() {
this.fireScriptEvent("init")
}
func (this *HTTPRequest) onRequest() {
if this.isDone || this.writer.isFinished {
return
}
this.fireScriptEvent("request")
}
// 触发事件
func (this *HTTPRequest) fireScriptEvent(eventType string) {
if SharedJSPool == nil {
return
}
if this.web.RequestScripts == nil {
return
}
var group *serverconfigs.ScriptGroupConfig
if eventType == "init" && this.web.RequestScripts.InitGroup != nil && this.web.RequestScripts.InitGroup.IsOn {
group = this.web.RequestScripts.InitGroup
} else if eventType == "request" && this.web.RequestScripts.RequestGroup != nil && this.web.RequestScripts.RequestGroup.IsOn {
group = this.web.RequestScripts.RequestGroup
}
if group == nil {
return
}
for _, script := range group.Scripts {
if this.isDone {
return
}
if !script.IsOn {
continue
}
if len(script.RealCode()) > 0 {
this.runScript(eventType, script.RealCode())
}
}
}
func (this *HTTPRequest) runScript(eventType string, script string) {
ctx, err := SharedJSPool.GetContext()
if err != nil {
remotelogs.Error("SCRIPT", "get context failed: "+err.Error())
return
}
ctx.SetServerId(this.ReqServer.Id)
defer SharedJSPool.PutContext(ctx)
var reqObjectId = ctx.AddGoRequestObject(this)
var respObjectId = ctx.AddGoResponseObject(this.writer)
script = `(function () {
let req = new gojs.net.http.Request()
req.setGoObject(` + types.String(reqObjectId) + `)
let resp = new gojs.net.http.Response()
resp.setGoObject(` + types.String(respObjectId) + `)
` + script + `
})()`
_, err = ctx.Run(script, "request."+eventType+".js")
if err != nil {
var errString = ""
jsErr, ok := err.(*v8go.JSError)
if ok {
var pieces = strings.Split(jsErr.Location, ":")
if len(pieces) < 3 {
errString = err.Error()
} else {
if strings.HasPrefix(pieces[0], "gojs") {
var line = types.Int(pieces[len(pieces)-2])
var scriptLine = ctx.ReadLineFromLibrary(pieces[0], line)
if len(scriptLine) > 0 {
if len(scriptLine) > 256 {
scriptLine = scriptLine[:256] + "..."
}
errString = jsErr.Error() + ", location: " + strings.Join(pieces[:len(pieces)-2], ":") + ":" + types.String(line) + ":" + pieces[len(pieces)-1] + ", code: " + scriptLine
}
}
if len(errString) == 0 {
var line = types.Int(pieces[len(pieces)-2])
var scriptLines = strings.Split(script, "\n")
var scriptLine = ""
if len(scriptLines) > line-1 {
scriptLine = scriptLines[line-1]
if len(scriptLine) > 256 {
scriptLine = scriptLine[:256] + "..."
}
}
line -= 6 /* 6是req和resp构造用的行数 */
errString = jsErr.Error() + ", location: " + strings.Join(pieces[:len(pieces)-2], ":") + ":" + types.String(line) + ":" + pieces[len(pieces)-1] + ", code: " + scriptLine
}
}
} else {
errString = err.Error()
}
remotelogs.ServerError(this.ReqServer.Id, "SCRIPT", "run "+eventType+" script failed: "+errString, nodeconfigs.NodeLogTypeRunScriptFailed, maps.Map{})
return
}
}