Skip to content

Commit

Permalink
fix: #46 BindStruct doesn't seem to work with env var substitution
Browse files Browse the repository at this point in the history
Signed-off-by: inhere <in.798@qq.com>
  • Loading branch information
inhere committed Jul 29, 2021
1 parent 8a26b20 commit 8a7c1f2
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
15 changes: 15 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ package config
import (
"fmt"
"os"
"reflect"
"strings"
"sync"

"github.com/gookit/goutil/envutil"
"github.com/mitchellh/mapstructure"
)

Expand Down Expand Up @@ -203,6 +205,19 @@ func newDefaultDecoderConfig() *mapstructure.DecoderConfig {
TagName: defaultStructTag,
// will auto convert string to int/uint
WeaklyTypedInput: true,
// DecodeHook: ParseEnvVarStringHookFunc,
}
}

// ParseEnvVarStringHookFunc returns a DecodeHookFunc that parse ENV var
func ParseEnvVarStringHookFunc() mapstructure.DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
if f.Kind() != reflect.String {
return data, nil
}

str := envutil.ParseEnvValue(data.(string))
return str, nil
}
}

Expand Down
5 changes: 5 additions & 0 deletions export.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ func (c *Config) Structure(key string, dst interface{}) error {
}
}

// parse env var
if c.opts.ParseEnv && bindConf.DecodeHook == nil {
bindConf.DecodeHook = ParseEnvVarStringHookFunc()
}

bindConf.Result = dst // set result struct ptr
decoder, err := mapstructure.NewDecoder(bindConf)
if err != nil {
Expand Down
50 changes: 49 additions & 1 deletion issues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import (
"github.com/gookit/config/v2/yaml"
"github.com/gookit/config/v2/yamlv3"
"github.com/gookit/goutil/dump"
"github.com/gookit/goutil/testutil"
"github.com/stretchr/testify/assert"
)

// https://github.com/gookit/config/issues/37
func TestIssues37(t *testing.T) {
func TestIssues_37(t *testing.T) {
is := assert.New(t)

c := config.New("test")
Expand Down Expand Up @@ -66,3 +67,50 @@ lang:
is.NoError(err)
dump.Println(c.Data())
}

// BindStruct doesn't seem to work with env var substitution
// https://github.com/gookit/config/issues/46
func TestIssues_46(t *testing.T) {
is := assert.New(t)

c := config.New("test").WithOptions(config.ParseEnv)
err := c.LoadStrings(config.JSON, `
{
"http": {
"port": "${HTTP_PORT|8080}"
}
}
`)

is.NoError(err)
dump.Println(c.Data())

val, _ := c.GetValue("http")
mp := val.(map[string]interface{})
dump.Println(mp)
is.Equal("${HTTP_PORT|8080}", mp["port"])

smp := c.StringMap("http")
dump.Println(smp)
is.Contains(smp, "port")
is.Equal("8080", smp["port"])

type Http struct {
Port int
}

h := &Http{}
err = c.BindStruct("http", h)
is.NoError(err)
dump.Println(h)
is.Equal(8080, h.Port)

testutil.MockEnvValue("HTTP_PORT", "19090", func(_ string) {
h := &Http{}
err = c.BindStruct("http", h)
is.NoError(err)
dump.Println(h)
is.Equal(19090, h.Port)
})

}

0 comments on commit 8a7c1f2

Please sign in to comment.