// 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 } }