From 22671c524edf776949f5ba6b3afb9e58001f2a3c Mon Sep 17 00:00:00 2001 From: shuo li Date: Wed, 17 Dec 2014 12:06:53 +0800 Subject: [PATCH 1/2] Fix subdomain, add test, space and comment fix --- context/input.go | 22 ++++++++++++++++------ context/input_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/context/input.go b/context/input.go index 3ed0bbe5..d9aa2634 100644 --- a/context/input.go +++ b/context/input.go @@ -27,7 +27,7 @@ import ( "github.com/astaxie/beego/session" ) -// BeegoInput operates the http request header ,data ,cookie and body. +// BeegoInput operates the http request header, data, cookie and body. // it also contains router params and current session. type BeegoInput struct { CruSession session.SessionStore @@ -153,12 +153,12 @@ func (input *BeegoInput) IsSecure() bool { return input.Scheme() == "https" } -// IsSecure returns boolean of this request is in webSocket. +// IsWebsocket returns boolean of this request is in webSocket. func (input *BeegoInput) IsWebsocket() bool { return input.Header("Upgrade") == "websocket" } -// IsSecure returns boolean of whether file uploads in this request or not.. +// IsUpload returns boolean of whether file uploads in this request or not.. func (input *BeegoInput) IsUpload() bool { return strings.Contains(input.Header("Content-Type"), "multipart/form-data") } @@ -189,16 +189,24 @@ func (input *BeegoInput) Proxy() []string { return []string{} } +// Referer returns http referer header. +func (input *BeegoInput) Referer() string { + return input.Header("Referer") +} + // Refer returns http referer header. func (input *BeegoInput) Refer() string { - return input.Header("Referer") + return input.Referer() } // SubDomains returns sub domain string. // if aa.bb.domain.com, returns aa.bb . func (input *BeegoInput) SubDomains() string { parts := strings.Split(input.Host(), ".") - return strings.Join(parts[:len(parts)-2], ".") + if len(parts) >= 3 { + return strings.Join(parts[:len(parts)-2], ".") + } + return "" } // Port returns request client port. @@ -237,6 +245,7 @@ func (input *BeegoInput) Query(key string) string { } // Header returns request header item string by a given string. +// if non-existed, return empty string. func (input *BeegoInput) Header(key string) string { return input.Request.Header.Get(key) } @@ -252,11 +261,12 @@ func (input *BeegoInput) Cookie(key string) string { } // Session returns current session item value by a given key. +// if non-existed, return empty string. func (input *BeegoInput) Session(key interface{}) interface{} { return input.CruSession.Get(key) } -// Body returns the raw request body data as bytes. +// CopyBody returns the raw request body data as bytes. func (input *BeegoInput) CopyBody() []byte { requestbody, _ := ioutil.ReadAll(input.Request.Body) input.Request.Body.Close() diff --git a/context/input_test.go b/context/input_test.go index ddd1a056..4566f6d6 100644 --- a/context/input_test.go +++ b/context/input_test.go @@ -70,3 +70,45 @@ func TestParse(t *testing.T) { } fmt.Println(user) } + +func TestSubDomain(t *testing.T) { + r, _ := http.NewRequest("GET", "http://www.example.com/?id=123&isok=true&ft=1.2&ol[0]=1&ol[1]=2&ul[]=str&ul[]=array&user.Name=astaxie", nil) + beegoInput := NewInput(r) + + subdomain := beegoInput.SubDomains() + if subdomain != "www" { + t.Fatal("Subdomain parse error, got" + subdomain) + } + + r, _ = http.NewRequest("GET", "http://localhost/", nil) + beegoInput.Request = r + if beegoInput.SubDomains() != "" { + t.Fatal("Subdomain parse error, should be empty, got " + beegoInput.SubDomains()) + } + + r, _ = http.NewRequest("GET", "http://aa.bb.example.com/", nil) + beegoInput.Request = r + if beegoInput.SubDomains() != "aa.bb" { + t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains()) + } + + /* TODO Fix this + r, _ = http.NewRequest("GET", "http://127.0.0.1/", nil) + beegoInput.Request = r + if beegoInput.SubDomains() != "" { + t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains()) + } + */ + + r, _ = http.NewRequest("GET", "http://example.com/", nil) + beegoInput.Request = r + if beegoInput.SubDomains() != "" { + t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains()) + } + + r, _ = http.NewRequest("GET", "http://aa.bb.cc.dd.example.com/", nil) + beegoInput.Request = r + if beegoInput.SubDomains() != "aa.bb.cc.dd" { + t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains()) + } +} From 572508ddd850f474404c0d18ce9dac023cbc5113 Mon Sep 17 00:00:00 2001 From: shuo li Date: Wed, 17 Dec 2014 17:02:46 +0800 Subject: [PATCH 2/2] Clean json config. Fix DefaultStrings --- config/json.go | 77 +++++++++++++++++++++------------------------ config/json_test.go | 15 +++++++-- 2 files changed, 48 insertions(+), 44 deletions(-) diff --git a/config/json.go b/config/json.go index ae86ea53..e2b53793 100644 --- a/config/json.go +++ b/config/json.go @@ -17,13 +17,10 @@ package config import ( "encoding/json" "errors" - "fmt" "io/ioutil" "os" - "path" "strings" "sync" - "time" ) // JsonConfig is a json config parser and implements Config interface. @@ -41,13 +38,19 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { if err != nil { return nil, err } + + return js.ParseData(content) +} + +// ParseData returns a ConfigContainer with json string +func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) { x := &JsonConfigContainer{ data: make(map[string]interface{}), } - err = json.Unmarshal(content, &x.data) + err := json.Unmarshal(data, &x.data) if err != nil { var wrappingArray []interface{} - err2 := json.Unmarshal(content, &wrappingArray) + err2 := json.Unmarshal(data, &wrappingArray) if err2 != nil { return nil, err } @@ -56,16 +59,6 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) { return x, nil } -func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) { - // Save memory data to temporary file - tmpName := path.Join(os.TempDir(), "beego", fmt.Sprintf("%d", time.Now().Nanosecond())) - os.MkdirAll(path.Dir(tmpName), os.ModePerm) - if err := ioutil.WriteFile(tmpName, data, 0655); err != nil { - return nil, err - } - return js.Parse(tmpName) -} - // A Config represents the json configuration. // Only when get value, support key as section:name type. type JsonConfigContainer struct { @@ -88,11 +81,10 @@ func (c *JsonConfigContainer) Bool(key string) (bool, error) { // DefaultBool return the bool value if has no error // otherwise return the defaultval func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool { - if v, err := c.Bool(key); err != nil { - return defaultval - } else { + if v, err := c.Bool(key); err == nil { return v } + return defaultval } // Int returns the integer value for a given key. @@ -110,11 +102,10 @@ func (c *JsonConfigContainer) Int(key string) (int, error) { // DefaultInt returns the integer value for a given key. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int { - if v, err := c.Int(key); err != nil { - return defaultval - } else { + if v, err := c.Int(key); err == nil { return v } + return defaultval } // Int64 returns the int64 value for a given key. @@ -132,11 +123,10 @@ func (c *JsonConfigContainer) Int64(key string) (int64, error) { // DefaultInt64 returns the int64 value for a given key. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 { - if v, err := c.Int64(key); err != nil { - return defaultval - } else { + if v, err := c.Int64(key); err == nil { return v } + return defaultval } // Float returns the float value for a given key. @@ -154,11 +144,10 @@ func (c *JsonConfigContainer) Float(key string) (float64, error) { // DefaultFloat returns the float64 value for a given key. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float64 { - if v, err := c.Float(key); err != nil { - return defaultval - } else { + if v, err := c.Float(key); err == nil { return v } + return defaultval } // String returns the string value for a given key. @@ -175,35 +164,37 @@ func (c *JsonConfigContainer) String(key string) string { // DefaultString returns the string value for a given key. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultString(key string, defaultval string) string { - if v := c.String(key); v == "" { - return defaultval - } else { + // TODO FIXME should not use "" to replace non existance + if v := c.String(key); v != "" { return v } + return defaultval } // Strings returns the []string value for a given key. func (c *JsonConfigContainer) Strings(key string) []string { + stringVal := c.String(key) + if stringVal == "" { + return []string{} + } return strings.Split(c.String(key), ";") } // DefaultStrings returns the []string value for a given key. // if err != nil return defaltval func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []string { - if v := c.Strings(key); len(v) == 0 { - return defaultval - } else { + if v := c.Strings(key); len(v) > 0 { return v } + return defaultval } // GetSection returns map for the given section func (c *JsonConfigContainer) GetSection(section string) (map[string]string, error) { if v, ok := c.data[section]; ok { return v.(map[string]string), nil - } else { - return nil, errors.New("not exist setction") } + return nil, errors.New("nonexist section " + section) } // SaveConfigFile save the config into file @@ -222,7 +213,7 @@ func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) { return err } -// WriteValue writes a new value for key. +// Set writes a new value for key. func (c *JsonConfigContainer) Set(key, val string) error { c.Lock() defer c.Unlock() @@ -241,18 +232,20 @@ func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) { // section.key or key func (c *JsonConfigContainer) getData(key string) interface{} { - c.RLock() - defer c.RUnlock() if len(key) == 0 { return nil } - sectionKey := strings.Split(key, "::") - if len(sectionKey) >= 2 { - curValue, ok := c.data[sectionKey[0]] + + c.RLock() + defer c.RUnlock() + + sectionKeys := strings.Split(key, "::") + if len(sectionKeys) >= 2 { + curValue, ok := c.data[sectionKeys[0]] if !ok { return nil } - for _, key := range sectionKey[1:] { + for _, key := range sectionKeys[1:] { if v, ok := curValue.(map[string]interface{}); ok { if curValue, ok = v[key]; !ok { return nil diff --git a/config/json_test.go b/config/json_test.go index 409e2c12..5aedae36 100644 --- a/config/json_test.go +++ b/config/json_test.go @@ -21,6 +21,7 @@ import ( var jsoncontext = `{ "appname": "beeapi", +"testnames": "foo;bar", "httpport": 8080, "mysqlport": 3600, "PI": 3.1415976, @@ -28,8 +29,8 @@ var jsoncontext = `{ "autorender": false, "copyrequestbody": true, "database": { - "host": "host", - "port": "port", + "host": "host", + "port": "port", "database": "database", "username": "username", "password": "password", @@ -122,6 +123,12 @@ func TestJson(t *testing.T) { if jsonconf.String("runmode") != "dev" { t.Fatal("runmode not equal to dev") } + if v := jsonconf.Strings("unknown"); len(v) > 0 { + t.Fatal("unknown strings, the length should be 0") + } + if v := jsonconf.Strings("testnames"); len(v) != 2 { + t.Fatal("testnames length should be 2") + } if v, err := jsonconf.Bool("autorender"); err != nil || v != false { t.Error(v) t.Fatal(err) @@ -179,4 +186,8 @@ func TestJson(t *testing.T) { if _, err := jsonconf.Bool("unknown"); err == nil { t.Error("unknown keys should return an error when expecting a Bool") } + + if !jsonconf.DefaultBool("unknow", true) { + t.Error("unknown keys with default value wrong") + } }