diff --git a/preprocess/expandvar.cli.go b/preprocess/expandvar.cli.go new file mode 100644 index 00000000..d87b4883 --- /dev/null +++ b/preprocess/expandvar.cli.go @@ -0,0 +1,30 @@ +//go:build cli + +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// General environment variables. + +package preprocess + +import ( + "os" + "strings" + + "github.com/dop251/goja" +) + +func getJsValue(vm *goja.Runtime, name string) goja.Value { + return vm.Get(name) +} + +func getEnvironMap() map[string]string { + m := make(map[string]string) + for _, e := range os.Environ() { + if i := strings.Index(e, "="); i >= 0 { + m[e[:i]] = e[i+1:] + } + } + return m +} diff --git a/preprocess/expandvar.go b/preprocess/expandvar.go index 6fa4564a..2a49a5a2 100644 --- a/preprocess/expandvar.go +++ b/preprocess/expandvar.go @@ -1,5 +1,3 @@ -//go:build cli - // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -9,9 +7,6 @@ package preprocess import ( - "os" - "strings" - "github.com/HexmosTech/lama2/utils" "github.com/dop251/goja" "github.com/rs/zerolog/log" @@ -39,7 +34,8 @@ func Expand(s string, vm *goja.Runtime, mapping map[string]string) string { // name. Leave the dollar character untouched. buf = append(buf, s[j]) } else { - jsVal := vm.Get(name) + // jsVal := vm.Get(name) + jsVal := getJsValue(vm, name) if jsVal != nil { buf = append(buf, []byte(jsVal.String())...) } else { @@ -66,23 +62,6 @@ func Expand(s string, vm *goja.Runtime, mapping map[string]string) string { return res2 } -func getEnvironMap() map[string]string { - m := make(map[string]string) - for _, e := range os.Environ() { - if i := strings.Index(e, "="); i >= 0 { - m[e[:i]] = e[i+1:] - } - } - return m -} - -// ExpandEnv replaces ${var} or $var in the string according to the values -// of the current environment variables. References to undefined -// variables are replaced by the empty string. -func ExpandEnv(s string, vm *goja.Runtime) string { - return Expand(s, vm, getEnvironMap()) -} - // isShellSpecialVar reports whether the character identifies a special // shell variable such as $*. func isShellSpecialVar(c uint8) bool { @@ -125,34 +104,9 @@ func getShellName(s string) (string, int) { return s[:i], i } -/* -// Getenv retrieves the value of the environment variable named by the key. -// It returns the value, which will be empty if the variable is not present. -// To distinguish between an empty value and an unset value, use LookupEnv. -func Getenv(key string) string { - testlog.Getenv(key) - v, _ := syscall.Getenv(key) - return v -} - -// LookupEnv retrieves the value of the environment variable named -// by the key. If the variable is present in the environment the -// value (which may be empty) is returned and the boolean is true. -// Otherwise the returned value will be empty and the boolean will -// be false. -func LookupEnv(key string) (string, bool) { - testlog.Getenv(key) - return syscall.Getenv(key) -} - -// Clearenv deletes all environment variables. -func Clearenv() { - syscall.Clearenv() -} - -// Environ returns a copy of strings representing the environment, -// in the form "key=value". -func Environ() []string { - return syscall.Environ() +// ExpandEnv replaces ${var} or $var in the string according to the values +// of the current environment variables. References to undefined +// variables are replaced by the empty string. +func ExpandEnv(s string, vm *goja.Runtime) string { + return Expand(s, vm, getEnvironMap()) } -*/ diff --git a/preprocess/expandvar.wasm.go b/preprocess/expandvar.wasm.go index 0969f823..768a23dc 100644 --- a/preprocess/expandvar.wasm.go +++ b/preprocess/expandvar.wasm.go @@ -3,66 +3,19 @@ package preprocess import ( - "syscall/js" - "github.com/HexmosTech/lama2/utils" + "github.com/dop251/goja" ) -// Expand replaces ${var} or $var in the string based on the mapping function. -// For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv). -func Expand(s string, mapping map[string]string) string { - var buf []byte - // ${} is all ASCII, so bytes are fine for this operation. - i := 0 - for j := 0; j < len(s); j++ { - if s[j] == '$' && j+1 < len(s) { - if buf == nil { - buf = make([]byte, 0, 2*len(s)) - } - buf = append(buf, s[i:j]...) - name, w := getShellName(s[j+1:]) - //nolint:all - if name == "" && w > 0 { - // Encountered invalid syntax; eat the - // characters. - } else if name == "" { - // Valid syntax, but $ was not followed by a - // name. Leave the dollar character untouched. - buf = append(buf, s[j]) - } else { - // jsVal := vm.Get(name) - jsVal := js.Global().Get(name) - - if jsVal.Truthy() { - buf = append(buf, []byte(jsVal.String())...) - } else { - val, ok := mapping[name] - if ok { - buf = append(buf, val...) - } else { - buf = append(buf, ""...) - } - } - } - j += w - i = j + 1 - } - } - res := "" - if buf == nil { - res = s - } else { - res = string(buf) + s[i:] - } - res2 := utils.RemoveUnquotedValueMarker(res) - return res2 +func getJsValue(vm *goja.Runtime, name string) goja.Value { + return js.Global().Get(name) } func getEnvironMap() map[string]string { result := make(map[string]string) - keysArray := js.Global().Get("Object").Call("keys", js.Global()) + keysArray := js.Global().Get("Object").Call("keys", js.Global()) keys := make([]string, keysArray.Length()) for i := 0; i < keysArray.Length(); i++ { keys[i] = keysArray.Index(i).String() @@ -72,56 +25,5 @@ func getEnvironMap() map[string]string { result[name] = value.String() } } - - return result } - -// ExpandEnv replaces ${var} or $var in the string according to the values -// of the current environment variables. References to undefined -// variables are replaced by the empty string. -func ExpandEnv(s string) string { - return Expand(s, getEnvironMap()) -} - -// isShellSpecialVar reports whether the character identifies a special -// shell variable such as $*. -func isShellSpecialVar(c uint8) bool { - switch c { - case '*', '#', '$', '@', '!', '?', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return true - } - return false -} - -// isAlphaNum reports whether the byte is an ASCII letter, number, or underscore -func isAlphaNum(c uint8) bool { - return c == '_' || '0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' -} - -// getShellName returns the name that begins the string and the number of bytes -// consumed to extract it. If the name is enclosed in {}, it's part of a ${} -// expansion and two more bytes are needed than the length of the name. -func getShellName(s string) (string, int) { - switch { - case s[0] == '{': - if len(s) > 2 && isShellSpecialVar(s[1]) && s[2] == '}' { - return s[1:2], 3 - } - // Scan to closing brace - for i := 1; i < len(s); i++ { - if s[i] == '}' { - if i == 1 { - return "", 2 // Bad syntax; eat "${}" - } - return s[1:i], i + 1 - } - } - return "", 1 // Bad syntax; eat "${" - case isShellSpecialVar(s[0]): - return s[0:1], 1 - } - // Scan alphanumerics. - var i int - return s[:i], i -} diff --git a/preprocess/preprocess.cli.go b/preprocess/preprocess.cli.go deleted file mode 100644 index 2c078a68..00000000 --- a/preprocess/preprocess.cli.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build cli - -// Package preprocess provides facilities to expand -// environment variables in `.l2` API files and return -// the contents -package preprocess - -import ( - "strings" - - "github.com/HexmosTech/gabs/v2" - "github.com/dop251/goja" - "github.com/rs/zerolog/log" -) - -func ProcessVarsInBlock(block *gabs.Container, vm *goja.Runtime) { - ExpandURL(block, vm) - ExpandHeaders(block, vm) - ExpandJSON(block, vm) -} - -func ExpandHeaders(block *gabs.Container, vm *goja.Runtime) { - headerMap := block.S("details", "headers") - log.Debug().Str("HeaderMap", headerMap.String()).Msg("") - if headerMap == nil { - return - } - newHeaderMap := gabs.New() - for k, v := range headerMap.ChildrenMap() { - log.Trace().Strs("Header pair", []string{k, " = ", v.String()}).Msg("") - key := ExpandEnv(k, vm) - val := ExpandEnv(v.Data().(*gabs.Container).Data().(string), vm) - valWrap := gabs.New() - valWrap.Set(val) - newHeaderMap.Set(valWrap, key) - } - block.Delete("details", "headers") - block.Set(newHeaderMap, "details", "headers") - log.Debug().Str("Expanded Header block", block.String()).Msg("") -} - -func ExpandURL(block *gabs.Container, vm *goja.Runtime) { - b := block.S("url", "value").Data().(string) - log.Debug().Str("Url block", b).Msg("") - url := ExpandEnv(b, vm) - block.Delete("url", "value") - block.Set(url, "url", "value") -} - -func ExpandJSON(block *gabs.Container, vm *goja.Runtime) { - log.Debug().Str("JSON block to be expanded", block.String()).Msg("") - dataBlock := block.S("details", "ip_data") - if dataBlock == nil { - return - } - dataBlockStr := dataBlock.String() - dataBlockStr = ExpandEnv(dataBlockStr, vm) - // dataBlockStr = escapeString(dataBlockStr) - dataBlockStr = strings.ReplaceAll(dataBlockStr, "\n", "") - log.Debug().Str("Expanded JSON data block", dataBlockStr).Msg("") - processedBlock, err := gabs.ParseJSON([]byte(dataBlockStr)) - if err != nil { - log.Error().Str("Preprocess JSON block issue", "").Msg("") - return - } - block.Delete("details", "ip_data") - block.Set(processedBlock, "details", "ip_data") - log.Debug().Str("Processed JSON block", block.String()).Msg("") -} diff --git a/preprocess/preprocess.go b/preprocess/preprocess.go index 4f641797..85135428 100644 --- a/preprocess/preprocess.go +++ b/preprocess/preprocess.go @@ -11,9 +11,13 @@ import ( "os" "path" "path/filepath" + "strings" + "github.com/HexmosTech/gabs/v2" "github.com/HexmosTech/godotenv" "github.com/HexmosTech/lama2/utils" + "github.com/dop251/goja" + "github.com/rs/zerolog/log" ) func debugOp(str string) { @@ -160,3 +164,58 @@ func LamaFile(inputFile string) (string, string) { return content, dir } + +func ProcessVarsInBlock(block *gabs.Container, vm *goja.Runtime) { + ExpandURL(block, vm) + ExpandHeaders(block, vm) + ExpandJSON(block, vm) +} + +func ExpandHeaders(block *gabs.Container, vm *goja.Runtime) { + headerMap := block.S("details", "headers") + log.Debug().Str("HeaderMap", headerMap.String()).Msg("") + if headerMap == nil { + return + } + newHeaderMap := gabs.New() + for k, v := range headerMap.ChildrenMap() { + log.Trace().Strs("Header pair", []string{k, " = ", v.String()}).Msg("") + key := ExpandEnv(k, vm) + val := ExpandEnv(v.Data().(*gabs.Container).Data().(string), vm) + valWrap := gabs.New() + valWrap.Set(val) + newHeaderMap.Set(valWrap, key) + } + block.Delete("details", "headers") + block.Set(newHeaderMap, "details", "headers") + log.Debug().Str("Expanded Header block", block.String()).Msg("") +} + +func ExpandURL(block *gabs.Container, vm *goja.Runtime) { + b := block.S("url", "value").Data().(string) + log.Debug().Str("Url block", b).Msg("") + url := ExpandEnv(b, vm) + block.Delete("url", "value") + block.Set(url, "url", "value") +} + +func ExpandJSON(block *gabs.Container, vm *goja.Runtime) { + log.Debug().Str("JSON block to be expanded", block.String()).Msg("") + dataBlock := block.S("details", "ip_data") + if dataBlock == nil { + return + } + dataBlockStr := dataBlock.String() + dataBlockStr = ExpandEnv(dataBlockStr, vm) + // dataBlockStr = escapeString(dataBlockStr) + dataBlockStr = strings.ReplaceAll(dataBlockStr, "\n", "") + log.Debug().Str("Expanded JSON data block", dataBlockStr).Msg("") + processedBlock, err := gabs.ParseJSON([]byte(dataBlockStr)) + if err != nil { + log.Error().Str("Preprocess JSON block issue", "").Msg("") + return + } + block.Delete("details", "ip_data") + block.Set(processedBlock, "details", "ip_data") + log.Debug().Str("Processed JSON block", block.String()).Msg("") +}