From 30e5634bdbdef56ca7ad026f611a852dbefc6e9e Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Mon, 18 Jan 2016 16:13:31 +0800 Subject: [PATCH 01/51] simplify the implementation of splitPath in tree.go --- tree.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tree.go b/tree.go index a6ffe062..72ef3dda 100644 --- a/tree.go +++ b/tree.go @@ -448,17 +448,11 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b // "/admin/" -> ["admin"] // "/admin/users" -> ["admin", "users"] func splitPath(key string) []string { + key = strings.Trim(key, "/ ") if key == "" { return []string{} } - elements := strings.Split(key, "/") - if elements[0] == "" { - elements = elements[1:] - } - if elements[len(elements)-1] == "" { - elements = elements[:len(elements)-1] - } - return elements + return strings.Split(key, "/") } // "admin" -> false, nil, "" From 35e340b9375bb76fa64d912d488fef082f132351 Mon Sep 17 00:00:00 2001 From: Henrique Bejgel Date: Mon, 18 Jan 2016 21:35:14 -0200 Subject: [PATCH 02/51] Checks if index is greater than the length of the wildcards. #1580 --- tree.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tree.go b/tree.go index 72ef3dda..ffd444d4 100644 --- a/tree.go +++ b/tree.go @@ -420,7 +420,11 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b if len(strs) == 2 { ctx.Input.SetParam(":ext", strs[1]) } - ctx.Input.SetParam(":path", path.Join(path.Join(wildcardValues[index:len(wildcardValues)-1]...), strs[0])) + if index > (len(wildcardValues) - 1) { + ctx.Input.SetParam(":path", "") + } else { + ctx.Input.SetParam(":path", path.Join(path.Join(wildcardValues[index:len(wildcardValues)-1]...), strs[0])) + } return true } // match :id From 5757e6548e76b6e7d9d38458b1f24f6b7798aa51 Mon Sep 17 00:00:00 2001 From: bradycao Date: Tue, 19 Jan 2016 10:14:16 +0800 Subject: [PATCH 03/51] =?UTF-8?q?template.go=20=E7=9A=84urlfor=20Func?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E6=9C=89=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit template.go 的urlfor Func注释有误 --- template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template.go b/template.go index 363c6754..1b62cf78 100644 --- a/template.go +++ b/template.go @@ -62,7 +62,7 @@ func init() { beegoTplFuncMap["lt"] = lt // < beegoTplFuncMap["ne"] = ne // != - beegoTplFuncMap["urlfor"] = URLFor // != + beegoTplFuncMap["urlfor"] = URLFor // build a URL to match a Controller and it's method } // AddFuncMap let user to register a func in the template. From 93b04e8a3b9f2f9d921f6cab089e95408d73cf6f Mon Sep 17 00:00:00 2001 From: nemtsevp Date: Thu, 21 Jan 2016 09:44:17 +0300 Subject: [PATCH 04/51] Exceptions in controller methods Exceptions in methods names should be changed according to controller.go --- router.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/router.go b/router.go index 726936de..82a602e1 100644 --- a/router.go +++ b/router.go @@ -62,12 +62,12 @@ var ( } // these beego.Controller's methods shouldn't reflect to AutoRouter exceptMethod = []string{"Init", "Prepare", "Finish", "Render", "RenderString", - "RenderBytes", "Redirect", "Abort", "StopRun", "UrlFor", "ServeJson", "ServeJsonp", - "ServeXml", "Input", "ParseForm", "GetString", "GetStrings", "GetInt", "GetBool", + "RenderBytes", "Redirect", "Abort", "StopRun", "UrlFor", "ServeJSON", "ServeJSONP", + "ServeXML", "Input", "ParseForm", "GetString", "GetStrings", "GetInt", "GetBool", "GetFloat", "GetFile", "SaveToFile", "StartSession", "SetSession", "GetSession", "DelSession", "SessionRegenerateID", "DestroySession", "IsAjax", "GetSecureCookie", "SetSecureCookie", "XsrfToken", "CheckXsrfCookie", "XsrfFormHtml", - "GetControllerAndAction"} + "GetControllerAndAction", "ServeFormatted"} urlPlaceholder = "{{placeholder}}" // DefaultAccessLogFilter will skip the accesslog if return true From cb5fd49612a57837555f0486cee1f3db140d1daa Mon Sep 17 00:00:00 2001 From: coseyo Date: Fri, 22 Jan 2016 18:03:02 +0800 Subject: [PATCH 05/51] fix conf load bug --- config.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index 8cf21530..e91ca28b 100644 --- a/config.go +++ b/config.go @@ -180,9 +180,10 @@ func init() { // now only support ini, next will support json. func ParseConfig() (err error) { if AppConfigPath == "" { - if utils.FileExists(filepath.Join("conf", "app.conf")) { - AppConfigPath = filepath.Join("conf", "app.conf") - } else { + // initialize default configurations + AppPath, _ := filepath.Abs(filepath.Dir(os.Args[0])) + AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") + if !utils.FileExists(AppConfigPath) { AppConfig = &beegoAppConfig{config.NewFakeConfig()} return } From be544f963e4e39e884b36500a23d219eb6c61716 Mon Sep 17 00:00:00 2001 From: ysqi Date: Sat, 23 Jan 2016 11:02:40 +0800 Subject: [PATCH 06/51] Support Parse Bool with more diffrent values ParseBool returns the boolean value represented by the string. It accepts 1, 1.0, t, T, TRUE, true, True, YES, yes, Yes,Y, y, ON, on, On, 0, 0.0, f, F, FALSE, false, False, NO, no, No, N,n, OFF, off, Off. Any other value returns an error. --- config/config.go | 38 +++++++++++ config/fake.go | 2 +- config/ini.go | 2 +- config/ini_test.go | 104 ++++++++++++++++++------------ config/json.go | 8 +-- config/json_test.go | 153 +++++++++++++++++++++++++------------------- config/xml/xml.go | 6 +- config/yaml/yaml.go | 7 +- 8 files changed, 202 insertions(+), 118 deletions(-) diff --git a/config/config.go b/config/config.go index da5d358b..e9df0f0e 100644 --- a/config/config.go +++ b/config/config.go @@ -106,3 +106,41 @@ func NewConfigData(adapterName string, data []byte) (Configer, error) { } return adapter.ParseData(data) } + +// ParseBool returns the boolean value represented by the string. +// +// It accepts 1, 1.0, t, T, TRUE, true, True, YES, yes, Yes,Y, y, ON, on, On, +// 0, 0.0, f, F, FALSE, false, False, NO, no, No, N,n, OFF, off, Off. +// Any other value returns an error. +func ParseBool(val interface{}) (value bool, err error) { + + if val != nil { + switch v := val.(type) { + case bool: + return v, nil + case string: + switch v { + case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On": + return true, nil + case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off": + return false, nil + } + case int8, int32, int64: + strV := fmt.Sprintf("%s", v) + if strV == "1" { + return true, nil + } else if strV == "0" { + return false, nil + } + case float64: + if v == 1 { + return true, nil + } else if v == 0 { + return false, nil + } + } + return false, fmt.Errorf("parsing %q: invalid syntax", val) + } else { + return false, fmt.Errorf("parsing : invalid syntax") + } +} diff --git a/config/fake.go b/config/fake.go index 50aa5d4a..6daaca2c 100644 --- a/config/fake.go +++ b/config/fake.go @@ -82,7 +82,7 @@ func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 { } func (c *fakeConfigContainer) Bool(key string) (bool, error) { - return strconv.ParseBool(c.getData(key)) + return ParseBool(c.getData(key)) } func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool { diff --git a/config/ini.go b/config/ini.go index 59e84e1e..6154b217 100644 --- a/config/ini.go +++ b/config/ini.go @@ -194,7 +194,7 @@ type IniConfigContainer struct { // Bool returns the boolean value for a given key. func (c *IniConfigContainer) Bool(key string) (bool, error) { - return strconv.ParseBool(c.getdata(key)) + return ParseBool(c.getdata(key)) } // DefaultBool returns the boolean value for a given key. diff --git a/config/ini_test.go b/config/ini_test.go index 7599ab8b..17643b6d 100644 --- a/config/ini_test.go +++ b/config/ini_test.go @@ -15,11 +15,15 @@ package config import ( + "fmt" "os" "testing" ) -var inicontext = ` +func TestIni(t *testing.T) { + + var ( + inicontext = ` ;comment one #comment two appname = beeapi @@ -29,6 +33,13 @@ PI = 3.1415976 runmode = "dev" autorender = false copyrequestbody = true +session= on +cookieon= off +newreg = OFF +needlogin = ON +enableSession = Y +enableCookie = N +flag = 1 [demo] key1="asta" key2 = "xie" @@ -36,7 +47,31 @@ CaseInsensitive = true peers = one;two;three ` -func TestIni(t *testing.T) { + keyValue = map[string]interface{}{ + "appname": "beeapi", + "httpport": 8080, + "mysqlport": int64(3600), + "pi": 3.1415976, + "runmode": "dev", + "autorender": false, + "copyrequestbody": true, + "session": true, + "cookieon": false, + "newreg": false, + "needlogin": true, + "enableSession": true, + "enableCookie": false, + "flag": true, + "demo::key1": "asta", + "demo::key2": "xie", + "demo::CaseInsensitive": true, + "demo::peers": []string{"one", "two", "three"}, + "null": "", + "demo2::key1": "", + "error": "", + } + ) + f, err := os.Create("testini.conf") if err != nil { t.Fatal(err) @@ -52,31 +87,31 @@ func TestIni(t *testing.T) { if err != nil { t.Fatal(err) } - if iniconf.String("appname") != "beeapi" { - t.Fatal("appname not equal to beeapi") - } - if port, err := iniconf.Int("httpport"); err != nil || port != 8080 { - t.Error(port) - t.Fatal(err) - } - if port, err := iniconf.Int64("mysqlport"); err != nil || port != 3600 { - t.Error(port) - t.Fatal(err) - } - if pi, err := iniconf.Float("PI"); err != nil || pi != 3.1415976 { - t.Error(pi) - t.Fatal(err) - } - if iniconf.String("runmode") != "dev" { - t.Fatal("runmode not equal to dev") - } - if v, err := iniconf.Bool("autorender"); err != nil || v != false { - t.Error(v) - t.Fatal(err) - } - if v, err := iniconf.Bool("copyrequestbody"); err != nil || v != true { - t.Error(v) - t.Fatal(err) + for k, v := range keyValue { + var err error + var value interface{} + switch v.(type) { + case int: + value, err = iniconf.Int(k) + case int64: + value, err = iniconf.Int64(k) + case float64: + value, err = iniconf.Float(k) + case bool: + value, err = iniconf.Bool(k) + case []string: + value = iniconf.Strings(k) + case string: + value = iniconf.String(k) + default: + value, err = iniconf.DIY(k) + } + if err != nil { + t.Fatalf("get key %q value fail,err %s", k, err) + } else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) { + t.Fatalf("get key %q value, want %v got %v .", k, v, value) + } + } if err = iniconf.Set("name", "astaxie"); err != nil { t.Fatal(err) @@ -84,20 +119,5 @@ func TestIni(t *testing.T) { if iniconf.String("name") != "astaxie" { t.Fatal("get name error") } - if iniconf.String("demo::key1") != "asta" { - t.Fatal("get demo.key1 error") - } - if iniconf.String("demo::key2") != "xie" { - t.Fatal("get demo.key2 error") - } - if v, err := iniconf.Bool("demo::caseinsensitive"); err != nil || v != true { - t.Fatal("get demo.caseinsensitive error") - } - - if data := iniconf.Strings("demo::peers"); len(data) != 3 { - t.Fatal("get strings error", data) - } else if data[0] != "one" { - t.Fatal("get first params error not equat to one") - } } diff --git a/config/json.go b/config/json.go index 65b4ac48..0bc1d456 100644 --- a/config/json.go +++ b/config/json.go @@ -17,6 +17,7 @@ package config import ( "encoding/json" "errors" + "fmt" "io/ioutil" "os" "strings" @@ -70,12 +71,9 @@ type JSONConfigContainer struct { func (c *JSONConfigContainer) Bool(key string) (bool, error) { val := c.getData(key) if val != nil { - if v, ok := val.(bool); ok { - return v, nil - } - return false, errors.New("not bool value") + return ParseBool(val) } - return false, errors.New("not exist key:" + key) + return false, fmt.Errorf("not exist key: %q", key) } // DefaultBool return the bool value if has no error diff --git a/config/json_test.go b/config/json_test.go index 5aedae36..9c06143e 100644 --- a/config/json_test.go +++ b/config/json_test.go @@ -15,34 +15,14 @@ package config import ( + "fmt" "os" "testing" ) -var jsoncontext = `{ -"appname": "beeapi", -"testnames": "foo;bar", -"httpport": 8080, -"mysqlport": 3600, -"PI": 3.1415976, -"runmode": "dev", -"autorender": false, -"copyrequestbody": true, -"database": { - "host": "host", - "port": "port", - "database": "database", - "username": "username", - "password": "password", - "conns":{ - "maxconnection":12, - "autoconnect":true, - "connectioninfo":"info" - } - } -}` +func TestJsonStartsWithArray(t *testing.T) { -var jsoncontextwitharray = `[ + const jsoncontextwitharray = `[ { "url": "user", "serviceAPI": "http://www.test.com/user" @@ -52,8 +32,6 @@ var jsoncontextwitharray = `[ "serviceAPI": "http://www.test.com/employee" } ]` - -func TestJsonStartsWithArray(t *testing.T) { f, err := os.Create("testjsonWithArray.conf") if err != nil { t.Fatal(err) @@ -90,6 +68,64 @@ func TestJsonStartsWithArray(t *testing.T) { } func TestJson(t *testing.T) { + + var ( + jsoncontext = `{ +"appname": "beeapi", +"testnames": "foo;bar", +"httpport": 8080, +"mysqlport": 3600, +"PI": 3.1415976, +"runmode": "dev", +"autorender": false, +"copyrequestbody": true, +"session": "on", +"cookieon": "off", +"newreg": "OFF", +"needlogin": "ON", +"enableSession": "Y", +"enableCookie": "N", +"flag": 1, +"database": { + "host": "host", + "port": "port", + "database": "database", + "username": "username", + "password": "password", + "conns":{ + "maxconnection":12, + "autoconnect":true, + "connectioninfo":"info" + } + } +}` + keyValue = map[string]interface{}{ + "appname": "beeapi", + "testnames": []string{"foo", "bar"}, + "httpport": 8080, + "mysqlport": int64(3600), + "PI": 3.1415976, + "runmode": "dev", + "autorender": false, + "copyrequestbody": true, + "session": true, + "cookieon": false, + "newreg": false, + "needlogin": true, + "enableSession": true, + "enableCookie": false, + "flag": true, + "database::host": "host", + "database::port": "port", + "database::database": "database", + "database::password": "password", + "database::conns::maxconnection": 12, + "database::conns::autoconnect": true, + "database::conns::connectioninfo": "info", + "unknown": "", + } + ) + f, err := os.Create("testjson.conf") if err != nil { t.Fatal(err) @@ -105,37 +141,32 @@ func TestJson(t *testing.T) { if err != nil { t.Fatal(err) } - if jsonconf.String("appname") != "beeapi" { - t.Fatal("appname not equal to beeapi") - } - if port, err := jsonconf.Int("httpport"); err != nil || port != 8080 { - t.Error(port) - t.Fatal(err) - } - if port, err := jsonconf.Int64("mysqlport"); err != nil || port != 3600 { - t.Error(port) - t.Fatal(err) - } - if pi, err := jsonconf.Float("PI"); err != nil || pi != 3.1415976 { - t.Error(pi) - t.Fatal(err) - } - 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) - } - if v, err := jsonconf.Bool("copyrequestbody"); err != nil || v != true { - t.Error(v) - t.Fatal(err) + + for k, v := range keyValue { + var err error + var value interface{} + switch v.(type) { + case int: + value, err = jsonconf.Int(k) + case int64: + value, err = jsonconf.Int64(k) + case float64: + value, err = jsonconf.Float(k) + case bool: + value, err = jsonconf.Bool(k) + case []string: + value = jsonconf.Strings(k) + case string: + value = jsonconf.String(k) + default: + value, err = jsonconf.DIY(k) + } + if err != nil { + t.Fatalf("get key %q value fatal,%V err %s", k, v, err) + } else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) { + t.Fatalf("get key %q value, want %v got %v .", k, v, value) + } + } if err = jsonconf.Set("name", "astaxie"); err != nil { t.Fatal(err) @@ -143,15 +174,7 @@ func TestJson(t *testing.T) { if jsonconf.String("name") != "astaxie" { t.Fatal("get name error") } - if jsonconf.String("database::host") != "host" { - t.Fatal("get database::host error") - } - if jsonconf.String("database::conns::connectioninfo") != "info" { - t.Fatal("get database::conns::connectioninfo error") - } - if maxconnection, err := jsonconf.Int("database::conns::maxconnection"); err != nil || maxconnection != 12 { - t.Fatal("get database::conns::maxconnection error") - } + if db, err := jsonconf.DIY("database"); err != nil { t.Fatal(err) } else if m, ok := db.(map[string]interface{}); !ok { diff --git a/config/xml/xml.go b/config/xml/xml.go index 4d48f7d2..662ef3d9 100644 --- a/config/xml/xml.go +++ b/config/xml/xml.go @@ -92,7 +92,11 @@ type ConfigContainer struct { // Bool returns the boolean value for a given key. func (c *ConfigContainer) Bool(key string) (bool, error) { - return strconv.ParseBool(c.data[key].(string)) + if v, ok := c.data[key]; ok { + return config.ParseBool(v) + } else { + return false, fmt.Errorf("not exist key: %q", key) + } } // DefaultBool return the bool value if has no error diff --git a/config/yaml/yaml.go b/config/yaml/yaml.go index f034d3ba..ccfd7b8b 100644 --- a/config/yaml/yaml.go +++ b/config/yaml/yaml.go @@ -121,10 +121,11 @@ type ConfigContainer struct { // Bool returns the boolean value for a given key. func (c *ConfigContainer) Bool(key string) (bool, error) { - if v, ok := c.data[key].(bool); ok { - return v, nil + if v, ok := c.data[key]; ok { + return config.ParseBool(v) + } else { + return false, fmt.Errorf("not exist key: %q", key) } - return false, errors.New("not bool value") } // DefaultBool return the bool value if has no error From 51ae45a7995db54356f6975499e4624617442f9b Mon Sep 17 00:00:00 2001 From: ysqi Date: Sat, 23 Jan 2016 14:53:52 +0800 Subject: [PATCH 07/51] Fixed #1607 --- config/ini.go | 40 +++++++++++++++++++++++++++-------- config/ini_test.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 9 deletions(-) diff --git a/config/ini.go b/config/ini.go index 59e84e1e..5a700a0b 100644 --- a/config/ini.go +++ b/config/ini.go @@ -27,7 +27,6 @@ import ( "strings" "sync" "time" - "unicode" ) var ( @@ -97,9 +96,11 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) { } if bComment != nil { line = bytes.TrimLeft(line, string(bComment)) - line = bytes.TrimLeftFunc(line, unicode.IsSpace) + // Need append to a new line if multi-line comments. + if comment.Len() > 0 { + comment.WriteByte('\n') + } comment.Write(line) - comment.WriteByte('\n') continue } @@ -299,14 +300,35 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) { } defer f.Close() + // Get section or key comments. Fixed #1607 + getCommentStr := func(section, key string) string { + comment, ok := "", false + if len(key) == 0 { + comment, ok = c.sectionComment[section] + } else { + comment, ok = c.keyComment[section+"."+key] + } + + if ok { + // Empty comment + if len(comment) == 0 || len(strings.TrimSpace(comment)) == 0 { + return string(bNumComment) + } + prefix := string(bNumComment) + // Add the line head character "#" + return prefix + strings.Replace(comment, lineBreak, lineBreak+prefix, -1) + } + return "" + } + buf := bytes.NewBuffer(nil) // Save default section at first place if dt, ok := c.data[defaultSection]; ok { for key, val := range dt { if key != " " { // Write key comments. - if v, ok := c.keyComment[key]; ok { - if _, err = buf.WriteString(string(bNumComment) + v + lineBreak); err != nil { + if v := getCommentStr(defaultSection, key); len(v) > 0 { + if _, err = buf.WriteString(v + lineBreak); err != nil { return err } } @@ -327,8 +349,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) { for section, dt := range c.data { if section != defaultSection { // Write section comments. - if v, ok := c.sectionComment[section]; ok { - if _, err = buf.WriteString(string(bNumComment) + v + lineBreak); err != nil { + if v := getCommentStr(section, ""); len(v) > 0 { + if _, err = buf.WriteString(v + lineBreak); err != nil { return err } } @@ -341,8 +363,8 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) { for key, val := range dt { if key != " " { // Write key comments. - if v, ok := c.keyComment[key]; ok { - if _, err = buf.WriteString(string(bNumComment) + v + lineBreak); err != nil { + if v := getCommentStr(section, key); len(v) > 0 { + if _, err = buf.WriteString(v + lineBreak); err != nil { return err } } diff --git a/config/ini_test.go b/config/ini_test.go index 7599ab8b..9f0bb8af 100644 --- a/config/ini_test.go +++ b/config/ini_test.go @@ -15,6 +15,7 @@ package config import ( + "io/ioutil" "os" "testing" ) @@ -101,3 +102,54 @@ func TestIni(t *testing.T) { } } + +func TestIniSave(t *testing.T) { + + const ( + inicontext = ` +app = app +;comment one +#comment two +# comment three +appname = beeapi +httpport = 8080 +# DB Info +# enable db +[dbinfo] +# db type name +# suport mysql,sqlserver +name = mysql +` + + saveResult = `app=app +#comment one +#comment two +# comment three +appname=beeapi +httpport=8080 + +# DB Info +# enable db +[dbinfo] +# db type name +# suport mysql,sqlserver +name=mysql + +` + ) + cfg, err := NewConfigData("ini", []byte(inicontext)) + if err != nil { + t.Fatal(err) + } + name := "newIniConfig.ini" + if err := cfg.SaveConfigFile(name); err != nil { + t.Fatal(err) + } + defer os.Remove(name) + + if data, err := ioutil.ReadFile(name); err != nil { + t.Fatal(err) + } else if string(data) != saveResult { + t.Fatal("different after save ini config file.") + } +} From ecf24640fd0f62c69bcba8e2099903f2e06dd7e5 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Sat, 23 Jan 2016 16:24:58 +0800 Subject: [PATCH 08/51] fix issue #1566 --- logs/conn.go | 9 ++++-- logs/console.go | 9 ++++-- logs/es/es.go | 8 ++--- logs/file.go | 45 +++------------------------ logs/log.go | 81 ++++++++++++++++++++++++++++++++++++++----------- logs/smtp.go | 4 +-- 6 files changed, 88 insertions(+), 68 deletions(-) diff --git a/logs/conn.go b/logs/conn.go index 3655bf51..2a29688a 100644 --- a/logs/conn.go +++ b/logs/conn.go @@ -19,6 +19,7 @@ import ( "io" "log" "net" + "time" ) // connWriter implements LoggerInterface. @@ -48,7 +49,7 @@ func (c *connWriter) Init(jsonconfig string) error { // WriteMsg write message in connection. // if connection is down, try to re-connect. -func (c *connWriter) WriteMsg(msg string, level int) error { +func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error { if level > c.Level { return nil } @@ -62,6 +63,10 @@ func (c *connWriter) WriteMsg(msg string, level int) error { if c.ReconnectOnMsg { defer c.innerWriter.Close() } + + logTimeStr := formatLogTime(when) + msg = logTimeStr + msg + c.lg.Println(msg) return nil } @@ -94,7 +99,7 @@ func (c *connWriter) connect() error { } c.innerWriter = conn - c.lg = log.New(conn, "", log.Ldate|log.Ltime) + c.lg = log.New(conn, "", 0) return nil } diff --git a/logs/console.go b/logs/console.go index 23e8ebca..48d1e5b2 100644 --- a/logs/console.go +++ b/logs/console.go @@ -19,6 +19,7 @@ import ( "log" "os" "runtime" + "time" ) // brush is a color join function @@ -53,7 +54,7 @@ type consoleWriter struct { // NewConsole create ConsoleWriter returning as LoggerInterface. func NewConsole() Logger { cw := &consoleWriter{ - lg: log.New(os.Stdout, "", log.Ldate|log.Ltime), + lg: log.New(os.Stdout, "", 0), Level: LevelDebug, } return cw @@ -69,10 +70,14 @@ func (c *consoleWriter) Init(jsonconfig string) error { } // WriteMsg write message in console. -func (c *consoleWriter) WriteMsg(msg string, level int) error { +func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { if level > c.Level { return nil } + + logTimeStr := formatLogTime(when) + msg = logTimeStr + msg + if goos := runtime.GOOS; goos == "windows" { c.lg.Println(msg) return nil diff --git a/logs/es/es.go b/logs/es/es.go index f8dc5f65..397ca2ef 100644 --- a/logs/es/es.go +++ b/logs/es/es.go @@ -48,16 +48,16 @@ func (el *esLogger) Init(jsonconfig string) error { } // WriteMsg will write the msg and level into es -func (el *esLogger) WriteMsg(msg string, level int) error { +func (el *esLogger) WriteMsg(when time.Time, msg string, level int) error { if level > el.Level { return nil } - t := time.Now() + vals := make(map[string]interface{}) - vals["@timestamp"] = t.Format(time.RFC3339) + vals["@timestamp"] = when.Format(time.RFC3339) vals["@msg"] = msg d := goes.Document{ - Index: fmt.Sprintf("%04d.%02d.%02d", t.Year(), t.Month(), t.Day()), + Index: fmt.Sprintf("%04d.%02d.%02d", when.Year(), when.Month(), when.Day()), Type: "logs", Fields: vals, } diff --git a/logs/file.go b/logs/file.go index 0eae734a..16bf29c2 100644 --- a/logs/file.go +++ b/logs/file.go @@ -114,50 +114,15 @@ func (w *fileLogWriter) needRotate(size int, day int) bool { } // WriteMsg write logger message into file. -func (w *fileLogWriter) WriteMsg(msg string, level int) error { +func (w *fileLogWriter) WriteMsg(when time.Time, msg string, level int) error { if level > w.Level { return nil } //2016/01/12 21:34:33 - now := time.Now() - y, mo, d := now.Date() - h, mi, s := now.Clock() - //len(2006/01/02 15:03:04)==19 - var buf [20]byte - t := 3 - for y >= 10 { - p := y / 10 - buf[t] = byte('0' + y - p*10) - y = p - t-- - } - buf[0] = byte('0' + y) - buf[4] = '/' - if mo > 9 { - buf[5] = '1' - buf[6] = byte('0' + mo - 9) - } else { - buf[5] = '0' - buf[6] = byte('0' + mo) - } - buf[7] = '/' - t = d / 10 - buf[8] = byte('0' + t) - buf[9] = byte('0' + d - t*10) - buf[10] = ' ' - t = h / 10 - buf[11] = byte('0' + t) - buf[12] = byte('0' + h - t*10) - buf[13] = ':' - t = mi / 10 - buf[14] = byte('0' + t) - buf[15] = byte('0' + mi - t*10) - buf[16] = ':' - t = s / 10 - buf[17] = byte('0' + t) - buf[18] = byte('0' + s - t*10) - buf[19] = ' ' - msg = string(buf[0:]) + msg + "\n" + // now := time.Now() + d := when.Day() + logTimeStr := formatLogTime(when) + msg = logTimeStr + msg + "\n" if w.Rotate { if w.needRotate(len(msg), d) { diff --git a/logs/log.go b/logs/log.go index ccaaa3ad..0c4ac13a 100644 --- a/logs/log.go +++ b/logs/log.go @@ -40,6 +40,7 @@ import ( "runtime" "strconv" "sync" + "time" ) // RFC5424 log message levels. @@ -68,7 +69,7 @@ type loggerType func() Logger // Logger defines the behavior of a log provider. type Logger interface { Init(config string) error - WriteMsg(msg string, level int) error + WriteMsg(when time.Time, msg string, level int) error Destroy() Flush() } @@ -108,6 +109,7 @@ type nameLogger struct { type logMsg struct { level int msg string + when time.Time } var logMsgPool *sync.Pool @@ -173,16 +175,16 @@ func (bl *BeeLogger) DelLogger(adapterName string) error { return nil } -func (bl *BeeLogger) writeToLoggers(msg string, level int) { +func (bl *BeeLogger) writeToLoggers(when time.Time, msg string, level int) { for _, l := range bl.outputs { - err := l.WriteMsg(msg, level) + err := l.WriteMsg(when, msg, level) if err != nil { fmt.Fprintf(os.Stderr, "unable to WriteMsg to adapter:%v,error:%v\n", l.name, err) } } } -func (bl *BeeLogger) writeMsg(logLevel int, msg string) error { +func (bl *BeeLogger) writeMsg(logLevel int, msg string, when time.Time) error { if bl.enableFuncCallDepth { _, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth) if !ok { @@ -196,9 +198,10 @@ func (bl *BeeLogger) writeMsg(logLevel int, msg string) error { lm := logMsgPool.Get().(*logMsg) lm.level = logLevel lm.msg = msg + lm.when = when bl.msgChan <- lm } else { - bl.writeToLoggers(msg, logLevel) + bl.writeToLoggers(when, msg, logLevel) } return nil } @@ -231,7 +234,7 @@ func (bl *BeeLogger) startLogger() { for { select { case bm := <-bl.msgChan: - bl.writeToLoggers(bm.msg, bm.level) + bl.writeToLoggers(bm.when, bm.msg, bm.level) logMsgPool.Put(bm) } } @@ -243,7 +246,7 @@ func (bl *BeeLogger) Emergency(format string, v ...interface{}) { return } msg := fmt.Sprintf("[M] "+format, v...) - bl.writeMsg(LevelEmergency, msg) + bl.writeMsg(LevelEmergency, msg, time.Now()) } // Alert Log ALERT level message. @@ -252,7 +255,7 @@ func (bl *BeeLogger) Alert(format string, v ...interface{}) { return } msg := fmt.Sprintf("[A] "+format, v...) - bl.writeMsg(LevelAlert, msg) + bl.writeMsg(LevelAlert, msg, time.Now()) } // Critical Log CRITICAL level message. @@ -261,7 +264,7 @@ func (bl *BeeLogger) Critical(format string, v ...interface{}) { return } msg := fmt.Sprintf("[C] "+format, v...) - bl.writeMsg(LevelCritical, msg) + bl.writeMsg(LevelCritical, msg, time.Now()) } // Error Log ERROR level message. @@ -270,7 +273,7 @@ func (bl *BeeLogger) Error(format string, v ...interface{}) { return } msg := fmt.Sprintf("[E] "+format, v...) - bl.writeMsg(LevelError, msg) + bl.writeMsg(LevelError, msg, time.Now()) } // Warning Log WARNING level message. @@ -279,7 +282,7 @@ func (bl *BeeLogger) Warning(format string, v ...interface{}) { return } msg := fmt.Sprintf("[W] "+format, v...) - bl.writeMsg(LevelWarning, msg) + bl.writeMsg(LevelWarning, msg, time.Now()) } // Notice Log NOTICE level message. @@ -288,7 +291,7 @@ func (bl *BeeLogger) Notice(format string, v ...interface{}) { return } msg := fmt.Sprintf("[N] "+format, v...) - bl.writeMsg(LevelNotice, msg) + bl.writeMsg(LevelNotice, msg, time.Now()) } // Informational Log INFORMATIONAL level message. @@ -297,7 +300,7 @@ func (bl *BeeLogger) Informational(format string, v ...interface{}) { return } msg := fmt.Sprintf("[I] "+format, v...) - bl.writeMsg(LevelInformational, msg) + bl.writeMsg(LevelInformational, msg, time.Now()) } // Debug Log DEBUG level message. @@ -306,7 +309,7 @@ func (bl *BeeLogger) Debug(format string, v ...interface{}) { return } msg := fmt.Sprintf("[D] "+format, v...) - bl.writeMsg(LevelDebug, msg) + bl.writeMsg(LevelDebug, msg, time.Now()) } // Warn Log WARN level message. @@ -316,7 +319,7 @@ func (bl *BeeLogger) Warn(format string, v ...interface{}) { return } msg := fmt.Sprintf("[W] "+format, v...) - bl.writeMsg(LevelWarning, msg) + bl.writeMsg(LevelWarning, msg, time.Now()) } // Info Log INFO level message. @@ -326,7 +329,7 @@ func (bl *BeeLogger) Info(format string, v ...interface{}) { return } msg := fmt.Sprintf("[I] "+format, v...) - bl.writeMsg(LevelInformational, msg) + bl.writeMsg(LevelInformational, msg, time.Now()) } // Trace Log TRACE level message. @@ -336,7 +339,7 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) { return } msg := fmt.Sprintf("[D] "+format, v...) - bl.writeMsg(LevelDebug, msg) + bl.writeMsg(LevelDebug, msg, time.Now()) } // Flush flush all chan data. @@ -351,7 +354,7 @@ func (bl *BeeLogger) Close() { for { if len(bl.msgChan) > 0 { bm := <-bl.msgChan - bl.writeToLoggers(bm.msg, bm.level) + bl.writeToLoggers(bm.when, bm.msg, bm.level) logMsgPool.Put(bm) continue } @@ -362,3 +365,45 @@ func (bl *BeeLogger) Close() { l.Destroy() } } + +func formatLogTime(when time.Time) string { + y, mo, d := when.Date() + h, mi, s := when.Clock() + //len(2006/01/02 15:03:04)==19 + var buf [20]byte + t := 3 + for y >= 10 { + p := y / 10 + buf[t] = byte('0' + y - p*10) + y = p + t-- + } + buf[0] = byte('0' + y) + buf[4] = '/' + if mo > 9 { + buf[5] = '1' + buf[6] = byte('0' + mo - 9) + } else { + buf[5] = '0' + buf[6] = byte('0' + mo) + } + buf[7] = '/' + t = d / 10 + buf[8] = byte('0' + t) + buf[9] = byte('0' + d - t*10) + buf[10] = ' ' + t = h / 10 + buf[11] = byte('0' + t) + buf[12] = byte('0' + h - t*10) + buf[13] = ':' + t = mi / 10 + buf[14] = byte('0' + t) + buf[15] = byte('0' + mi - t*10) + buf[16] = ':' + t = s / 10 + buf[17] = byte('0' + t) + buf[18] = byte('0' + s - t*10) + buf[19] = ' ' + + return string(buf[0:]) +} diff --git a/logs/smtp.go b/logs/smtp.go index 748462f9..47f5a0c6 100644 --- a/logs/smtp.go +++ b/logs/smtp.go @@ -126,7 +126,7 @@ func (s *SMTPWriter) sendMail(hostAddressWithPort string, auth smtp.Auth, fromAd // WriteMsg write message in smtp writer. // it will send an email with subject and only this message. -func (s *SMTPWriter) WriteMsg(msg string, level int) error { +func (s *SMTPWriter) WriteMsg(when time.Time, msg string, level int) error { if level > s.Level { return nil } @@ -140,7 +140,7 @@ func (s *SMTPWriter) WriteMsg(msg string, level int) error { // and send the email all in one step. contentType := "Content-Type: text/plain" + "; charset=UTF-8" mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.FromAddress + "<" + s.FromAddress + - ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", time.Now().Format("2006-01-02 15:04:05")) + msg) + ">\r\nSubject: " + s.Subject + "\r\n" + contentType + "\r\n\r\n" + fmt.Sprintf(".%s", when.Format("2006-01-02 15:04:05")) + msg) return s.sendMail(s.Host, auth, s.FromAddress, s.RecipientAddresses, mailmsg) } From cbc7f43e88984a145d7ba85ff2ab7fb0dfc9e6e9 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Sat, 23 Jan 2016 02:32:09 +0800 Subject: [PATCH 09/51] fix issue #1601 --- beego.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/beego.go b/beego.go index 04f02071..7aa6b221 100644 --- a/beego.go +++ b/beego.go @@ -69,10 +69,13 @@ func Run(params ...string) { func initBeforeHTTPRun() { // if AppConfigPath is setted or conf/app.conf exist + /* err := ParseConfig() if err != nil { panic(err) } + */ + var err error //init log for adaptor, config := range BConfig.Log.Outputs { err = BeeLogger.SetLogger(adaptor, config) From 007af6224eba5a61bd9d71124f3cbf84ca61ed29 Mon Sep 17 00:00:00 2001 From: ysqi Date: Sat, 23 Jan 2016 19:13:19 +0800 Subject: [PATCH 10/51] Fixed #1586 --- tree.go | 19 +++++++++----- tree_test.go | 74 +++++++++++++++++++++------------------------------- 2 files changed, 43 insertions(+), 50 deletions(-) diff --git a/tree.go b/tree.go index 72ef3dda..a151b15d 100644 --- a/tree.go +++ b/tree.go @@ -15,12 +15,11 @@ package beego import ( + "github.com/astaxie/beego/context" + "github.com/astaxie/beego/utils" "path" "regexp" "strings" - - "github.com/astaxie/beego/context" - "github.com/astaxie/beego/utils" ) var ( @@ -438,7 +437,9 @@ func (leaf *leafInfo) match(wildcardValues []string, ctx *context.Context) (ok b } matches := leaf.regexps.FindStringSubmatch(path.Join(wildcardValues...)) for i, match := range matches[1:] { - ctx.Input.SetParam(leaf.wildcards[i], match) + if i < len(leaf.wildcards) { + ctx.Input.SetParam(leaf.wildcards[i], match) + } } return true } @@ -536,13 +537,19 @@ func splitSegment(key string) (bool, []string, string) { continue } } - if v == ':' { + // Escape Sequence '\' + if i > 0 && key[i-1] == '\\' { + out = append(out, v) + } else if v == ':' { param = make([]rune, 0) start = true } else if v == '(' { startexp = true start = false - params = append(params, ":"+string(param)) + if len(param) > 0 { + params = append(params, ":"+string(param)) + param = make([]rune, 0) + } paramsNum++ expt = make([]rune, 0) expt = append(expt, '(') diff --git a/tree_test.go b/tree_test.go index 15ab7ce4..168c9020 100644 --- a/tree_test.go +++ b/tree_test.go @@ -15,9 +15,9 @@ package beego import ( - "testing" - "github.com/astaxie/beego/context" + "strings" + "testing" ) type testinfo struct { @@ -57,6 +57,9 @@ func init() { "/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg", map[string]string{":width": "48", ":height": "48", ":ext": "jpg", ":path": "05ac66d9bda00a3acf948c43e306fc9a"}}) routers = append(routers, testinfo{"/v1/shop/:id:int", "/v1/shop/123", map[string]string{":id": "123"}}) + routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(a)", map[string]string{":id": "123"}}) + routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(b)", map[string]string{":id": "123"}}) + routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(c)", map[string]string{":id": "123"}}) routers = append(routers, testinfo{"/:year:int/:month:int/:id/:endid", "/1111/111/aaa/aaa", map[string]string{":year": "1111", ":month": "111", ":id": "aaa", ":endid": "aaa"}}) routers = append(routers, testinfo{"/v1/shop/:id/:name", "/v1/shop/123/nike", map[string]string{":id": "123", ":name": "nike"}}) routers = append(routers, testinfo{"/v1/shop/:id/account", "/v1/shop/123/account", map[string]string{":id": "123"}}) @@ -245,48 +248,31 @@ func TestSplitPath(t *testing.T) { } func TestSplitSegment(t *testing.T) { - b, w, r := splitSegment("admin") - if b || len(w) != 0 || r != "" { - t.Fatal("admin should return false, nil, ''") + + items := map[string]struct { + isReg bool + params []string + regStr string + }{ + "admin": {false, nil, ""}, + "*": {true, []string{":splat"}, ""}, + "*.*": {true, []string{".", ":path", ":ext"}, ""}, + ":id": {true, []string{":id"}, ""}, + "?:id": {true, []string{":", ":id"}, ""}, + ":id:int": {true, []string{":id"}, "([0-9]+)"}, + ":name:string": {true, []string{":name"}, `([\w]+)`}, + ":id([0-9]+)": {true, []string{":id"}, `([0-9]+)`}, + ":id([0-9]+)_:name": {true, []string{":id", ":name"}, `([0-9]+)_(.+)`}, + ":id(.+)_cms.html": {true, []string{":id"}, `(.+)_cms.html`}, + "cms_:id(.+)_:page(.+).html": {true, []string{":id", ":page"}, `cms_(.+)_(.+).html`}, + `:app(a|b|c)`: {true, []string{":app"}, `(a|b|c)`}, + `:app\((a|b|c)\)`: {true, []string{":app"}, `(.+)\((a|b|c)\)`}, } - b, w, r = splitSegment("*") - if !b || len(w) != 1 || w[0] != ":splat" || r != "" { - t.Fatal("* should return true, [:splat], ''") - } - b, w, r = splitSegment("*.*") - if !b || len(w) != 3 || w[1] != ":path" || w[2] != ":ext" || w[0] != "." || r != "" { - t.Fatal("admin should return true,[. :path :ext], ''") - } - b, w, r = splitSegment(":id") - if !b || len(w) != 1 || w[0] != ":id" || r != "" { - t.Fatal(":id should return true, [:id], ''") - } - b, w, r = splitSegment("?:id") - if !b || len(w) != 2 || w[0] != ":" || w[1] != ":id" || r != "" { - t.Fatal("?:id should return true, [: :id], ''") - } - b, w, r = splitSegment(":id:int") - if !b || len(w) != 1 || w[0] != ":id" || r != "([0-9]+)" { - t.Fatal(":id:int should return true, [:id], '([0-9]+)'") - } - b, w, r = splitSegment(":name:string") - if !b || len(w) != 1 || w[0] != ":name" || r != `([\w]+)` { - t.Fatal(`:name:string should return true, [:name], '([\w]+)'`) - } - b, w, r = splitSegment(":id([0-9]+)") - if !b || len(w) != 1 || w[0] != ":id" || r != `([0-9]+)` { - t.Fatal(`:id([0-9]+) should return true, [:id], '([0-9]+)'`) - } - b, w, r = splitSegment(":id([0-9]+)_:name") - if !b || len(w) != 2 || w[0] != ":id" || w[1] != ":name" || r != `([0-9]+)_(.+)` { - t.Fatal(`:id([0-9]+)_:name should return true, [:id :name], '([0-9]+)_(.+)'`) - } - b, w, r = splitSegment(":id(.+)_cms.html") - if !b || len(w) != 1 || w[0] != ":id" || r != `(.+)_cms.html` { - t.Fatal(":id_cms.html should return true, [:id], '(.+)_cms.html'") - } - b, w, r = splitSegment("cms_:id(.+)_:page(.+).html") - if !b || len(w) != 2 || w[0] != ":id" || w[1] != ":page" || r != `cms_(.+)_(.+).html` { - t.Fatal(":id_cms.html should return true, [:id :page], cms_(.+)_(.+).html") + + for pattern, v := range items { + b, w, r := splitSegment(pattern) + if b != v.isReg || r != v.regStr || strings.Join(w, ",") != strings.Join(v.params, ",") { + t.Fatalf("%s should return %t,%s,%q, got %t,%s,%q", pattern, v.isReg, v.params, v.regStr, b, w, r) + } } } From 4c1cfc13868e7779570dc7b3c6494c428160308d Mon Sep 17 00:00:00 2001 From: coseyo Date: Sun, 24 Jan 2016 00:18:16 +0800 Subject: [PATCH 11/51] fix path issue --- config.go | 11 ++++++++++- parser.go | 6 +++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/config.go b/config.go index e91ca28b..d090d247 100644 --- a/config.go +++ b/config.go @@ -103,6 +103,8 @@ var ( BConfig *Config // AppConfig is the instance of Config, store the config information from file AppConfig *beegoAppConfig + // AppPath is the absolute path to the app + AppPath string // AppConfigPath is the path to the config files AppConfigPath string // AppConfigProvider is the provider for the config, default is ini @@ -179,9 +181,16 @@ func init() { // ParseConfig parsed default config file. // now only support ini, next will support json. func ParseConfig() (err error) { + AppPath, _ := filepath.Abs(filepath.Dir(os.Args[0])) + workPath, _ := os.Getwd() + workPath, _ = filepath.Abs(workPath) + + if workPath != AppPath { + os.Chdir(AppPath) + } + if AppConfigPath == "" { // initialize default configurations - AppPath, _ := filepath.Abs(filepath.Dir(os.Args[0])) AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") if !utils.FileExists(AppConfigPath) { AppConfig = &beegoAppConfig{config.NewFakeConfig()} diff --git a/parser.go b/parser.go index b14d74b9..f23f4720 100644 --- a/parser.go +++ b/parser.go @@ -130,7 +130,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat } func genRouterCode() { - os.Mkdir("routers", 0755) + os.Mkdir(path.Join(AppPath, "routers"), 0755) Info("generate router from comments") var ( globalinfo string @@ -172,7 +172,7 @@ func genRouterCode() { } } if globalinfo != "" { - f, err := os.Create(path.Join("routers", commentFilename)) + f, err := os.Create(path.Join(AppPath, "routers", commentFilename)) if err != nil { panic(err) } @@ -182,7 +182,7 @@ func genRouterCode() { } func compareFile(pkgRealpath string) bool { - if !utils.FileExists(path.Join("routers", commentFilename)) { + if !utils.FileExists(path.Join(AppPath, "routers", commentFilename)) { return true } if utils.FileExists(lastupdateFilename) { From 3031bdd1762bfb4a04fb36ea764e4c1209a5c9d8 Mon Sep 17 00:00:00 2001 From: coseyo Date: Sun, 24 Jan 2016 00:40:03 +0800 Subject: [PATCH 12/51] fix test error --- config.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/config.go b/config.go index d090d247..ea329596 100644 --- a/config.go +++ b/config.go @@ -185,18 +185,17 @@ func ParseConfig() (err error) { workPath, _ := os.Getwd() workPath, _ = filepath.Abs(workPath) - if workPath != AppPath { - os.Chdir(AppPath) - } - if AppConfigPath == "" { // initialize default configurations AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") - if !utils.FileExists(AppConfigPath) { + if utils.FileExists(AppConfigPath) && workPath != AppPath { + os.Chdir(AppPath) + } else { AppConfig = &beegoAppConfig{config.NewFakeConfig()} return } } + AppConfig, err = newAppConfig(AppConfigProvider, AppConfigPath) if err != nil { return err From 09d3d89c6f0444f92c03a382bc2cdade17363af1 Mon Sep 17 00:00:00 2001 From: coseyo Date: Sun, 24 Jan 2016 00:47:37 +0800 Subject: [PATCH 13/51] fix test error again --- config.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index ea329596..3ceae12e 100644 --- a/config.go +++ b/config.go @@ -188,14 +188,16 @@ func ParseConfig() (err error) { if AppConfigPath == "" { // initialize default configurations AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") - if utils.FileExists(AppConfigPath) && workPath != AppPath { - os.Chdir(AppPath) - } else { + if !utils.FileExists(AppConfigPath) { AppConfig = &beegoAppConfig{config.NewFakeConfig()} return } } + if workPath != AppPath { + os.Chdir(AppPath) + } + AppConfig, err = newAppConfig(AppConfigProvider, AppConfigPath) if err != nil { return err From 3d7354b9d286eb75cbcc1b760b20741a2f2f6394 Mon Sep 17 00:00:00 2001 From: ysqi Date: Sun, 24 Jan 2016 11:10:04 +0800 Subject: [PATCH 14/51] import reset --- tree.go | 5 +++-- tree_test.go | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tree.go b/tree.go index a151b15d..3f413325 100644 --- a/tree.go +++ b/tree.go @@ -15,11 +15,12 @@ package beego import ( - "github.com/astaxie/beego/context" - "github.com/astaxie/beego/utils" "path" "regexp" "strings" + + "github.com/astaxie/beego/context" + "github.com/astaxie/beego/utils" ) var ( diff --git a/tree_test.go b/tree_test.go index 168c9020..9f21c18c 100644 --- a/tree_test.go +++ b/tree_test.go @@ -15,9 +15,10 @@ package beego import ( - "github.com/astaxie/beego/context" "strings" "testing" + + "github.com/astaxie/beego/context" ) type testinfo struct { From a80feb00b82ff6d7c2e7dbe2914564dc13e05e5f Mon Sep 17 00:00:00 2001 From: miraclesu Date: Mon, 25 Jan 2016 18:11:50 +0800 Subject: [PATCH 15/51] Fix utils mail from field can't including Chinese bug --- utils/mail.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/mail.go b/utils/mail.go index 1d80a039..bebce610 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -231,11 +231,10 @@ func (e *Email) Send() error { if e.From == "" || len(to) == 0 { return errors.New("Must specify at least one From address and one To address") } - from, err := mail.ParseAddress(e.From) + from, err := mail.ParseAddress(e.Username) if err != nil { return err } - e.From = from.String() raw, err := e.Bytes() if err != nil { return err From 0e17e2a3d28b9d68b8ce5e1e41a476e9cb52c09d Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Mon, 25 Jan 2016 20:20:53 +0800 Subject: [PATCH 16/51] accept @JessonChan suggestion --- logs/log.go | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/logs/log.go b/logs/log.go index 0c4ac13a..076a9766 100644 --- a/logs/log.go +++ b/logs/log.go @@ -184,7 +184,8 @@ func (bl *BeeLogger) writeToLoggers(when time.Time, msg string, level int) { } } -func (bl *BeeLogger) writeMsg(logLevel int, msg string, when time.Time) error { +func (bl *BeeLogger) writeMsg(logLevel int, msg string) error { + when := time.Now() if bl.enableFuncCallDepth { _, file, line, ok := runtime.Caller(bl.loggerFuncCallDepth) if !ok { @@ -246,7 +247,7 @@ func (bl *BeeLogger) Emergency(format string, v ...interface{}) { return } msg := fmt.Sprintf("[M] "+format, v...) - bl.writeMsg(LevelEmergency, msg, time.Now()) + bl.writeMsg(LevelEmergency, msg) } // Alert Log ALERT level message. @@ -255,7 +256,7 @@ func (bl *BeeLogger) Alert(format string, v ...interface{}) { return } msg := fmt.Sprintf("[A] "+format, v...) - bl.writeMsg(LevelAlert, msg, time.Now()) + bl.writeMsg(LevelAlert, msg) } // Critical Log CRITICAL level message. @@ -264,7 +265,7 @@ func (bl *BeeLogger) Critical(format string, v ...interface{}) { return } msg := fmt.Sprintf("[C] "+format, v...) - bl.writeMsg(LevelCritical, msg, time.Now()) + bl.writeMsg(LevelCritical, msg) } // Error Log ERROR level message. @@ -273,7 +274,7 @@ func (bl *BeeLogger) Error(format string, v ...interface{}) { return } msg := fmt.Sprintf("[E] "+format, v...) - bl.writeMsg(LevelError, msg, time.Now()) + bl.writeMsg(LevelError, msg) } // Warning Log WARNING level message. @@ -282,7 +283,7 @@ func (bl *BeeLogger) Warning(format string, v ...interface{}) { return } msg := fmt.Sprintf("[W] "+format, v...) - bl.writeMsg(LevelWarning, msg, time.Now()) + bl.writeMsg(LevelWarning, msg) } // Notice Log NOTICE level message. @@ -291,7 +292,7 @@ func (bl *BeeLogger) Notice(format string, v ...interface{}) { return } msg := fmt.Sprintf("[N] "+format, v...) - bl.writeMsg(LevelNotice, msg, time.Now()) + bl.writeMsg(LevelNotice, msg) } // Informational Log INFORMATIONAL level message. @@ -300,7 +301,7 @@ func (bl *BeeLogger) Informational(format string, v ...interface{}) { return } msg := fmt.Sprintf("[I] "+format, v...) - bl.writeMsg(LevelInformational, msg, time.Now()) + bl.writeMsg(LevelInformational, msg) } // Debug Log DEBUG level message. @@ -309,7 +310,7 @@ func (bl *BeeLogger) Debug(format string, v ...interface{}) { return } msg := fmt.Sprintf("[D] "+format, v...) - bl.writeMsg(LevelDebug, msg, time.Now()) + bl.writeMsg(LevelDebug, msg) } // Warn Log WARN level message. @@ -319,7 +320,7 @@ func (bl *BeeLogger) Warn(format string, v ...interface{}) { return } msg := fmt.Sprintf("[W] "+format, v...) - bl.writeMsg(LevelWarning, msg, time.Now()) + bl.writeMsg(LevelWarning, msg) } // Info Log INFO level message. @@ -329,7 +330,7 @@ func (bl *BeeLogger) Info(format string, v ...interface{}) { return } msg := fmt.Sprintf("[I] "+format, v...) - bl.writeMsg(LevelInformational, msg, time.Now()) + bl.writeMsg(LevelInformational, msg) } // Trace Log TRACE level message. @@ -339,7 +340,7 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) { return } msg := fmt.Sprintf("[D] "+format, v...) - bl.writeMsg(LevelDebug, msg, time.Now()) + bl.writeMsg(LevelDebug, msg) } // Flush flush all chan data. From bcac4bb8e3631e77fe1a0e0d6fd312a4f3c1b099 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Mon, 25 Jan 2016 20:53:25 +0800 Subject: [PATCH 17/51] accept @JessonChan suggestion --- logs/conn.go | 3 +-- logs/console.go | 5 +---- logs/file.go | 3 +-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/logs/conn.go b/logs/conn.go index 2a29688a..5d78467b 100644 --- a/logs/conn.go +++ b/logs/conn.go @@ -64,8 +64,7 @@ func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error { defer c.innerWriter.Close() } - logTimeStr := formatLogTime(when) - msg = logTimeStr + msg + msg = formatLogTime(when) + msg c.lg.Println(msg) return nil diff --git a/logs/console.go b/logs/console.go index 48d1e5b2..e6da0df9 100644 --- a/logs/console.go +++ b/logs/console.go @@ -74,10 +74,7 @@ func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { if level > c.Level { return nil } - - logTimeStr := formatLogTime(when) - msg = logTimeStr + msg - + msg = formatLogTime(when) + msg if goos := runtime.GOOS; goos == "windows" { c.lg.Println(msg) return nil diff --git a/logs/file.go b/logs/file.go index 16bf29c2..f277317c 100644 --- a/logs/file.go +++ b/logs/file.go @@ -121,8 +121,7 @@ func (w *fileLogWriter) WriteMsg(when time.Time, msg string, level int) error { //2016/01/12 21:34:33 // now := time.Now() d := when.Day() - logTimeStr := formatLogTime(when) - msg = logTimeStr + msg + "\n" + msg = formatLogTime(when) + msg + "\n" if w.Rotate { if w.needRotate(len(msg), d) { From fdce4af9c824d8064436820fbe74fa5fe73e68c2 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 20:53:52 +0800 Subject: [PATCH 18/51] fix #1619 --- orm/types.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/orm/types.go b/orm/types.go index 5fac5fed..1c8460b2 100644 --- a/orm/types.go +++ b/orm/types.go @@ -162,6 +162,12 @@ type QuerySeter interface { // qs.RelatedSel("profile").One(&user) // user.Profile.Age = 32 RelatedSel(params ...interface{}) QuerySeter + // Set Distinct + // for example: + // o.QueryTable("policy").Filter("Groups__Group__Users__User", user). + // Distinct(). + // All(&permissions) + Distinct() QuerySeter // return QuerySeter execution result number // for example: // num, err = qs.Filter("profile__age__gt", 28).Count() From 87650ce8bcad80f103e67787651a0059b3054aaa Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 20:57:41 +0800 Subject: [PATCH 19/51] make golint happy --- config/config.go | 4 +--- config/xml/xml.go | 3 +-- config/yaml/yaml.go | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/config/config.go b/config/config.go index e9df0f0e..c0afec05 100644 --- a/config/config.go +++ b/config/config.go @@ -113,7 +113,6 @@ func NewConfigData(adapterName string, data []byte) (Configer, error) { // 0, 0.0, f, F, FALSE, false, False, NO, no, No, N,n, OFF, off, Off. // Any other value returns an error. func ParseBool(val interface{}) (value bool, err error) { - if val != nil { switch v := val.(type) { case bool: @@ -140,7 +139,6 @@ func ParseBool(val interface{}) (value bool, err error) { } } return false, fmt.Errorf("parsing %q: invalid syntax", val) - } else { - return false, fmt.Errorf("parsing : invalid syntax") } + return false, fmt.Errorf("parsing : invalid syntax") } diff --git a/config/xml/xml.go b/config/xml/xml.go index 662ef3d9..ffb32862 100644 --- a/config/xml/xml.go +++ b/config/xml/xml.go @@ -94,9 +94,8 @@ type ConfigContainer struct { func (c *ConfigContainer) Bool(key string) (bool, error) { if v, ok := c.data[key]; ok { return config.ParseBool(v) - } else { - return false, fmt.Errorf("not exist key: %q", key) } + return false, fmt.Errorf("not exist key: %q", key) } // DefaultBool return the bool value if has no error diff --git a/config/yaml/yaml.go b/config/yaml/yaml.go index ccfd7b8b..9a96ac92 100644 --- a/config/yaml/yaml.go +++ b/config/yaml/yaml.go @@ -123,9 +123,8 @@ type ConfigContainer struct { func (c *ConfigContainer) Bool(key string) (bool, error) { if v, ok := c.data[key]; ok { return config.ParseBool(v) - } else { - return false, fmt.Errorf("not exist key: %q", key) } + return false, fmt.Errorf("not exist key: %q", key) } // DefaultBool return the bool value if has no error From 7e3ad5bcb010beb9c8a01fbdb475c655f9f0ebe2 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 21:08:29 +0800 Subject: [PATCH 20/51] fix #1585 --- hooks.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hooks.go b/hooks.go index 78abf8ef..59b10b32 100644 --- a/hooks.go +++ b/hooks.go @@ -68,13 +68,11 @@ func registerSession() error { } func registerTemplate() error { - if BConfig.WebConfig.AutoRender { - if err := BuildTemplate(BConfig.WebConfig.ViewsPath); err != nil { - if BConfig.RunMode == DEV { - Warn(err) - } - return err + if err := BuildTemplate(BConfig.WebConfig.ViewsPath); err != nil { + if BConfig.RunMode == DEV { + Warn(err) } + return err } return nil } From e7d4452af0c8f51007c60a379a55dce39a9d3da3 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 21:13:56 +0800 Subject: [PATCH 21/51] add golint and go test --- .travis.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c59cef61..bb98eebb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,9 @@ language: go go: - - 1.5.1 - + - 1.5.3 + - 1.4.3 + - 1.3.3 services: - redis-server - mysql @@ -24,7 +25,14 @@ install: - go get github.com/couchbase/go-couchbase - go get github.com/siddontang/ledisdb/config - go get github.com/siddontang/ledisdb/ledis + - go get code.google.com/p/go.tools/cmd/vet + - go get code.google.com/p/go.tools/cmd/cover + - go get github.com/golang/lint/golint before_script: - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" - sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi" - sh -c "if [ '$ORM_DRIVER' = 'sqlite' ]; then touch $TRAVIS_BUILD_DIR/orm_test.db; fi" +script: + - go vet -x ./... + - $HOME/gopath/bin/golint ./... + - go test -v ./... From 3dac344ff690ba7db854b33f789e88af268206fe Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 21:20:10 +0800 Subject: [PATCH 22/51] fix the vet url --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bb98eebb..30ec5d4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,8 +25,7 @@ install: - go get github.com/couchbase/go-couchbase - go get github.com/siddontang/ledisdb/config - go get github.com/siddontang/ledisdb/ledis - - go get code.google.com/p/go.tools/cmd/vet - - go get code.google.com/p/go.tools/cmd/cover + - go get golang.org/x/tools/cmd/vet - go get github.com/golang/lint/golint before_script: - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" From f8004b69adb338fd945409f1fa96c181433b9fa4 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 21:33:57 +0800 Subject: [PATCH 23/51] fix the go vet --- config/json_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/json_test.go b/config/json_test.go index 9c06143e..df663461 100644 --- a/config/json_test.go +++ b/config/json_test.go @@ -162,7 +162,7 @@ func TestJson(t *testing.T) { value, err = jsonconf.DIY(k) } if err != nil { - t.Fatalf("get key %q value fatal,%V err %s", k, v, err) + t.Fatalf("get key %q value fatal,%v err %s", k, v, err) } else if fmt.Sprintf("%v", v) != fmt.Sprintf("%v", value) { t.Fatalf("get key %q value, want %v got %v .", k, v, value) } From 15e9ba19c0ea4342f79aa09a3fd404a8b9ae3369 Mon Sep 17 00:00:00 2001 From: astaxie Date: Mon, 25 Jan 2016 21:39:44 +0800 Subject: [PATCH 24/51] fix the range only used in Go 1.4 fix #1623 --- tree.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tree.go b/tree.go index ffd444d4..07034bb4 100644 --- a/tree.go +++ b/tree.go @@ -141,7 +141,7 @@ func (t *Tree) addtree(segments []string, tree *Tree, wildcards []string, reg st regexpStr = "([^.]+).(.+)" params = params[1:] } else { - for range params { + for _ = range params { regexpStr = "([^/]+)/" + regexpStr } } @@ -254,7 +254,7 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, regexpStr = "/([^.]+).(.+)" params = params[1:] } else { - for range params { + for _ = range params { regexpStr = "/([^/]+)" + regexpStr } } From 4de91f675da1c4a68360e1298ab362c91b8c4068 Mon Sep 17 00:00:00 2001 From: miraclesu Date: Mon, 25 Jan 2016 22:29:45 +0800 Subject: [PATCH 25/51] show from when Config from is empty --- utils/mail.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/utils/mail.go b/utils/mail.go index bebce610..07043149 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -74,9 +74,6 @@ func NewEMail(config string) *Email { if err != nil { return nil } - if e.From == "" { - e.From = e.Username - } return e } @@ -228,13 +225,19 @@ func (e *Email) Send() error { to := make([]string, 0, len(e.To)+len(e.Cc)+len(e.Bcc)) to = append(append(append(to, e.To...), e.Cc...), e.Bcc...) // Check to make sure there is at least one recipient and one "From" address - if e.From == "" || len(to) == 0 { - return errors.New("Must specify at least one From address and one To address") + if len(to) == 0 { + return errors.New("Must specify at least one To address") } + from, err := mail.ParseAddress(e.Username) if err != nil { return err } + + if len(e.From) == 0 { + e.From = from.String() + } + raw, err := e.Bytes() if err != nil { return err From 5930f27da7d776c2ddf23b53287a1967dbb85a4e Mon Sep 17 00:00:00 2001 From: miraclesu Date: Mon, 25 Jan 2016 22:55:40 +0800 Subject: [PATCH 26/51] Fix mail Chinese subject garbled bug --- utils/mail.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/mail.go b/utils/mail.go index 07043149..125fddd5 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -237,6 +237,9 @@ func (e *Email) Send() error { if len(e.From) == 0 { e.From = from.String() } + // use mail's RFC 5322 to encode any string + sub := mail.Address{e.Subject, ""} + e.Subject = strings.Trim(sub.String(), " <@>") raw, err := e.Bytes() if err != nil { From d1481ea659253f6f66bae053fd358f66c68f384c Mon Sep 17 00:00:00 2001 From: coseyo Date: Mon, 25 Jan 2016 23:00:09 +0800 Subject: [PATCH 27/51] move assignment to init --- config.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/config.go b/config.go index 3ceae12e..bf9077a7 100644 --- a/config.go +++ b/config.go @@ -113,9 +113,15 @@ var ( TemplateCache map[string]*template.Template // GlobalSessions is the instance for the session manager GlobalSessions *session.Manager + + workPath string ) func init() { + AppPath, _ = filepath.Abs(filepath.Dir(os.Args[0])) + workPath, _ = os.Getwd() + workPath, _ = filepath.Abs(workPath) + BConfig = &Config{ AppName: "beego", RunMode: DEV, @@ -181,10 +187,6 @@ func init() { // ParseConfig parsed default config file. // now only support ini, next will support json. func ParseConfig() (err error) { - AppPath, _ := filepath.Abs(filepath.Dir(os.Args[0])) - workPath, _ := os.Getwd() - workPath, _ = filepath.Abs(workPath) - if AppConfigPath == "" { // initialize default configurations AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") From 61e9dc74c9099dfc6f5bf9cbe10ecbd3987be2db Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 26 Jan 2016 00:27:02 +0800 Subject: [PATCH 28/51] make sure the memcache testing success --- cache/memcache/memcache_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cache/memcache/memcache_test.go b/cache/memcache/memcache_test.go index 8d98c177..0c8c57f2 100644 --- a/cache/memcache/memcache_test.go +++ b/cache/memcache/memcache_test.go @@ -37,7 +37,7 @@ func TestMemcacheCache(t *testing.T) { t.Error("check err") } - time.Sleep(10 * time.Second) + time.Sleep(11 * time.Second) if bm.IsExist("astaxie") { t.Error("check err") From b5a07c6ba89dd7aa0903ba09fd3a5059a3318f3b Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 26 Jan 2016 09:20:49 +0800 Subject: [PATCH 29/51] log file name bug fixed this bug happens when daily rotate. ex,when it is 2016-01-22 23:59:59 and need a rotate,the file name should named with 2016-01-22 but named with 2016-01-23(next day) --- logs/file.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/logs/file.go b/logs/file.go index f277317c..e7401922 100644 --- a/logs/file.go +++ b/logs/file.go @@ -127,7 +127,7 @@ func (w *fileLogWriter) WriteMsg(when time.Time, msg string, level int) error { if w.needRotate(len(msg), d) { w.Lock() if w.needRotate(len(msg), d) { - if err := w.doRotate(); err != nil { + if err := w.doRotate(when); err != nil { fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err) } @@ -200,7 +200,7 @@ func (w *fileLogWriter) lines() (int, error) { // DoRotate means it need to write file in new file. // new file name like xx.2013-01-01.2.log -func (w *fileLogWriter) doRotate() error { +func (w *fileLogWriter) doRotate(logTime time.Time) error { _, err := os.Lstat(w.Filename) if err != nil { return err @@ -215,7 +215,7 @@ func (w *fileLogWriter) doRotate() error { suffix = ".log" } for ; err == nil && num <= 999; num++ { - fName = filenameOnly + fmt.Sprintf(".%s.%03d%s", time.Now().Format("2006-01-02"), num, suffix) + fName = filenameOnly + fmt.Sprintf(".%s.%03d%s", logTime.Format("2006-01-02"), num, suffix) _, err = os.Lstat(fName) } // return error if the last file checked still existed From f2567bc114f8f01bc2e8493bf13a1a1bcfc72c64 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 26 Jan 2016 09:29:04 +0800 Subject: [PATCH 30/51] some typo fixed --- logs/console.go | 24 ++++++++++++------------ logs/file.go | 5 +---- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/logs/console.go b/logs/console.go index e6da0df9..b717a12e 100644 --- a/logs/console.go +++ b/logs/console.go @@ -35,14 +35,14 @@ func newBrush(color string) brush { } var colors = []brush{ - newBrush("1;37"), // Emergency white - newBrush("1;36"), // Alert cyan - newBrush("1;35"), // Critical magenta - newBrush("1;31"), // Error red - newBrush("1;33"), // Warning yellow - newBrush("1;32"), // Notice green + newBrush("1;37"), // Emergency white + newBrush("1;36"), // Alert cyan + newBrush("1;35"), // Critical magenta + newBrush("1;31"), // Error red + newBrush("1;33"), // Warning yellow + newBrush("1;32"), // Notice green newBrush("1;34"), // Informational blue - newBrush("1;34"), // Debug blue + newBrush("1;34"), // Debug blue } // consoleWriter implements LoggerInterface and writes messages to terminal. @@ -61,12 +61,12 @@ func NewConsole() Logger { } // Init init console logger. -// jsonconfig like '{"level":LevelTrace}'. -func (c *consoleWriter) Init(jsonconfig string) error { - if len(jsonconfig) == 0 { +// jsonConfig like '{"level":LevelTrace}'. +func (c *consoleWriter) Init(jsonConfig string) error { + if len(jsonConfig) == 0 { return nil } - return json.Unmarshal([]byte(jsonconfig), c) + return json.Unmarshal([]byte(jsonConfig), c) } // WriteMsg write message in console. @@ -75,7 +75,7 @@ func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { return nil } msg = formatLogTime(when) + msg - if goos := runtime.GOOS; goos == "windows" { + if runtime.GOOS == "windows" { c.lg.Println(msg) return nil } diff --git a/logs/file.go b/logs/file.go index e7401922..3a042164 100644 --- a/logs/file.go +++ b/logs/file.go @@ -118,19 +118,16 @@ func (w *fileLogWriter) WriteMsg(when time.Time, msg string, level int) error { if level > w.Level { return nil } - //2016/01/12 21:34:33 - // now := time.Now() - d := when.Day() msg = formatLogTime(when) + msg + "\n" if w.Rotate { + d := when.Day() if w.needRotate(len(msg), d) { w.Lock() if w.needRotate(len(msg), d) { if err := w.doRotate(when); err != nil { fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err) } - } w.Unlock() } From e11d150e8b989a258c0a99576f7485b879c8a151 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 26 Jan 2016 09:35:39 +0800 Subject: [PATCH 31/51] replace \t with space --- logs/console.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/logs/console.go b/logs/console.go index b717a12e..10d8e8b2 100644 --- a/logs/console.go +++ b/logs/console.go @@ -35,14 +35,14 @@ func newBrush(color string) brush { } var colors = []brush{ - newBrush("1;37"), // Emergency white - newBrush("1;36"), // Alert cyan - newBrush("1;35"), // Critical magenta - newBrush("1;31"), // Error red - newBrush("1;33"), // Warning yellow - newBrush("1;32"), // Notice green - newBrush("1;34"), // Informational blue - newBrush("1;34"), // Debug blue + newBrush("1;37"), // Emergency white + newBrush("1;36"), // Alert cyan + newBrush("1;35"), // Critical magenta + newBrush("1;31"), // Error red + newBrush("1;33"), // Warning yellow + newBrush("1;32"), // Notice green + newBrush("1;34"), // Informational blue + newBrush("1;34"), // Debug blue } // consoleWriter implements LoggerInterface and writes messages to terminal. From f26d360ec9b82d58389799dfa3ee1d2383894c6a Mon Sep 17 00:00:00 2001 From: miraclesu Date: Tue, 26 Jan 2016 10:33:48 +0800 Subject: [PATCH 32/51] Fix vet fail --- utils/mail.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/mail.go b/utils/mail.go index 125fddd5..0a961204 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -235,11 +235,11 @@ func (e *Email) Send() error { } if len(e.From) == 0 { - e.From = from.String() + e.From = e.Username } - // use mail's RFC 5322 to encode any string - sub := mail.Address{e.Subject, ""} - e.Subject = strings.Trim(sub.String(), " <@>") + // use mail's RFC 2047 to encode any string + sub := mail.Address{Name: e.Subject, Address: ""} + e.Subject = strings.TrimRight(sub.String(), " <@>") raw, err := e.Bytes() if err != nil { From bf870eb9a26af47b5bdfee9e3cb2ded180e80247 Mon Sep 17 00:00:00 2001 From: miraclesu Date: Tue, 26 Jan 2016 20:50:03 +0800 Subject: [PATCH 33/51] mv mime.QEncoding.Encode logic to mail it is named qEncode --- utils/mail.go | 76 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/utils/mail.go b/utils/mail.go index 0a961204..10555a0a 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -31,10 +31,13 @@ import ( "path/filepath" "strconv" "strings" + "sync" ) const ( maxLineLength = 76 + + upperhex = "0123456789ABCDEF" ) // Email is the type used for email messages @@ -238,8 +241,7 @@ func (e *Email) Send() error { e.From = e.Username } // use mail's RFC 2047 to encode any string - sub := mail.Address{Name: e.Subject, Address: ""} - e.Subject = strings.TrimRight(sub.String(), " <@>") + e.Subject = qEncode("utf-8", e.Subject) raw, err := e.Bytes() if err != nil { @@ -347,3 +349,73 @@ func base64Wrap(w io.Writer, b []byte) { w.Write(out) } } + +// Encode returns the encoded-word form of s. If s is ASCII without special +// characters, it is returned unchanged. The provided charset is the IANA +// charset name of s. It is case insensitive. +// RFC 2047 encoded-word +func qEncode(charset, s string) string { + if !needsEncoding(s) { + return s + } + return encodeWord(charset, s) +} + +func needsEncoding(s string) bool { + for _, b := range s { + if (b < ' ' || b > '~') && b != '\t' { + return true + } + } + return false +} + +// encodeWord encodes a string into an encoded-word. +func encodeWord(charset, s string) string { + buf := getBuffer() + + buf.WriteString("=?") + buf.WriteString(charset) + buf.WriteByte('?') + buf.WriteByte('q') + buf.WriteByte('?') + + enc := make([]byte, 3) + for i := 0; i < len(s); i++ { + b := s[i] + switch { + case b == ' ': + buf.WriteByte('_') + case b <= '~' && b >= '!' && b != '=' && b != '?' && b != '_': + buf.WriteByte(b) + default: + enc[0] = '=' + enc[1] = upperhex[b>>4] + enc[2] = upperhex[b&0x0f] + buf.Write(enc) + } + } + buf.WriteString("?=") + + es := buf.String() + putBuffer(buf) + return es +} + +var bufPool = sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, +} + +func getBuffer() *bytes.Buffer { + return bufPool.Get().(*bytes.Buffer) +} + +func putBuffer(buf *bytes.Buffer) { + if buf.Len() > 1024 { + return + } + buf.Reset() + bufPool.Put(buf) +} From d9e6250d08aa12e1f84e4236b1994e2ecbae7679 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Wed, 27 Jan 2016 00:10:21 +0800 Subject: [PATCH 34/51] fix config logic --- beego.go | 12 +-------- config.go | 80 +++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 28 deletions(-) diff --git a/beego.go b/beego.go index 7aa6b221..68a76e52 100644 --- a/beego.go +++ b/beego.go @@ -15,7 +15,6 @@ package beego import ( - "fmt" "os" "path/filepath" "strconv" @@ -76,15 +75,6 @@ func initBeforeHTTPRun() { } */ var err error - //init log - for adaptor, config := range BConfig.Log.Outputs { - err = BeeLogger.SetLogger(adaptor, config) - if err != nil { - fmt.Printf("%s with the config `%s` got err:%s\n", adaptor, config, err) - } - } - - SetLogFuncCall(BConfig.Log.FileLineNum) //init hooks AddAPPStartHook(registerMime) @@ -95,7 +85,7 @@ func initBeforeHTTPRun() { AddAPPStartHook(registerAdmin) for _, hk := range hooks { - if err := hk(); err != nil { + if err = hk(); err != nil { panic(err) } } diff --git a/config.go b/config.go index e91ca28b..246c53f0 100644 --- a/config.go +++ b/config.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "strings" + "fmt" "github.com/astaxie/beego/config" "github.com/astaxie/beego/session" @@ -103,14 +104,15 @@ var ( BConfig *Config // AppConfig is the instance of Config, store the config information from file AppConfig *beegoAppConfig - // AppConfigPath is the path to the config files - AppConfigPath string - // AppConfigProvider is the provider for the config, default is ini - AppConfigProvider = "ini" // TemplateCache stores template caching TemplateCache map[string]*template.Template // GlobalSessions is the instance for the session manager GlobalSessions *session.Manager + + // AppConfigPath is the path to the config files + AppConfigPath string + // AppConfigProvider is the provider for the config, default is ini + AppConfigProvider = "ini" ) func init() { @@ -173,22 +175,26 @@ func init() { Outputs: map[string]string{"console": ""}, }, } - ParseConfig() + + AppConfigPath = getDefaultAppConfigPath() + + if !utils.FileExists(AppConfigPath) { + AppConfig = &beegoAppConfig{config.NewFakeConfig()} + return + } + + parseConfig(AppConfigPath) +} + +func getDefaultAppConfigPath() string { + // default config path + AppPath, _ := filepath.Abs(filepath.Dir(os.Args[0])) + return filepath.Join(AppPath, "conf", "app.conf") } -// ParseConfig parsed default config file. // now only support ini, next will support json. -func ParseConfig() (err error) { - if AppConfigPath == "" { - // initialize default configurations - AppPath, _ := filepath.Abs(filepath.Dir(os.Args[0])) - AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") - if !utils.FileExists(AppConfigPath) { - AppConfig = &beegoAppConfig{config.NewFakeConfig()} - return - } - } - AppConfig, err = newAppConfig(AppConfigProvider, AppConfigPath) +func parseConfig(appConfigPath string) (err error) { + AppConfig, err = newAppConfig(AppConfigProvider, appConfigPath) if err != nil { return err } @@ -242,6 +248,8 @@ func ParseConfig() (err error) { BConfig.WebConfig.Session.SessionCookieLifeTime = AppConfig.DefaultInt("SessionCookieLifeTime", BConfig.WebConfig.Session.SessionCookieLifeTime) BConfig.WebConfig.Session.SessionAutoSetCookie = AppConfig.DefaultBool("SessionAutoSetCookie", BConfig.WebConfig.Session.SessionAutoSetCookie) BConfig.WebConfig.Session.SessionDomain = AppConfig.DefaultString("SessionDomain", BConfig.WebConfig.Session.SessionDomain) + BConfig.Log.AccessLogs = AppConfig.DefaultBool("LogAccessLogs", BConfig.Log.AccessLogs) + BConfig.Log.FileLineNum = AppConfig.DefaultBool("LogFileLineNum", BConfig.Log.FileLineNum) if sd := AppConfig.String("StaticDir"); sd != "" { for k := range BConfig.WebConfig.StaticDir { @@ -274,9 +282,47 @@ func ParseConfig() (err error) { BConfig.WebConfig.StaticExtensionsToGzip = fileExts } } + + if lo := AppConfig.String("LogOutputs"); lo != "" { + los := strings.Split(lo, ";") + for _, v := range los { + if logType2Config := strings.SplitN(v, ",", 2); len(logType2Config) == 2 { + BConfig.Log.Outputs[logType2Config[0]] = logType2Config[1] + } else { + continue + } + } + } + + //init log + BeeLogger.Close() + for adaptor, config := range BConfig.Log.Outputs { + err = BeeLogger.SetLogger(adaptor, config) + if err != nil { + fmt.Printf("%s with the config `%s` got err:%s\n", adaptor, config, err) + } + } + SetLogFuncCall(BConfig.Log.FileLineNum) + return nil } +// LoadAppConfig allow developer to apply a config file +func LoadAppConfig(configPath string, adapterName string) error { + absConfigPath, err := filepath.Abs(configPath) + if err != nil { + return err + } + if absConfigPath == AppConfigPath { + return nil + } + + AppConfigPath = absConfigPath + AppConfigProvider = adapterName + + return parseConfig(AppConfigPath) +} + type beegoAppConfig struct { innerConfig config.Configer } From 330b3b193118b58cd442e8004532d48033035cea Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Wed, 27 Jan 2016 00:17:56 +0800 Subject: [PATCH 35/51] enhancement code --- config.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config.go b/config.go index 246c53f0..a86ad34c 100644 --- a/config.go +++ b/config.go @@ -20,6 +20,7 @@ import ( "path/filepath" "strings" "fmt" + "errors" "github.com/astaxie/beego/config" "github.com/astaxie/beego/session" @@ -313,6 +314,11 @@ func LoadAppConfig(configPath string, adapterName string) error { if err != nil { return err } + + if !utils.FileExists(absConfigPath) { + return errors.New(fmt.Sprintf("the target config file: %s don't exist!", configPath)) + } + if absConfigPath == AppConfigPath { return nil } From 20efd5236e7e5f6a99a44d53e5ac7a54adb53b9e Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Wed, 27 Jan 2016 00:42:07 +0800 Subject: [PATCH 36/51] fix bug --- logs/log.go | 1 + 1 file changed, 1 insertion(+) diff --git a/logs/log.go b/logs/log.go index ccaaa3ad..14757929 100644 --- a/logs/log.go +++ b/logs/log.go @@ -361,4 +361,5 @@ func (bl *BeeLogger) Close() { l.Flush() l.Destroy() } + bl.outputs = nil } From e549d0fd9c6675e11a08af96fdb4e04511389ef1 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Wed, 27 Jan 2016 12:13:26 +0800 Subject: [PATCH 37/51] move some code piece --- config.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config.go b/config.go index 570faacb..e72f770c 100644 --- a/config.go +++ b/config.go @@ -124,6 +124,10 @@ func init() { workPath, _ = os.Getwd() workPath, _ = filepath.Abs(workPath) + if workPath != AppPath { + os.Chdir(AppPath) + } + BConfig = &Config{ AppName: "beego", RunMode: DEV, @@ -195,10 +199,6 @@ func init() { // now only support ini, next will support json. func parseConfig(appConfigPath string) (err error) { - if workPath != AppPath { - os.Chdir(AppPath) - } - AppConfig, err = newAppConfig(AppConfigProvider, appConfigPath) if err != nil { return err From 321bcc606af089c74a7b980ba4962bb81cf2f862 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Wed, 27 Jan 2016 12:26:37 +0800 Subject: [PATCH 38/51] fix bug of test case --- staticfile_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/staticfile_test.go b/staticfile_test.go index d3333570..e7003366 100644 --- a/staticfile_test.go +++ b/staticfile_test.go @@ -8,9 +8,11 @@ import ( "io/ioutil" "os" "testing" + "path/filepath" ) -const licenseFile = "./LICENSE" +var currentWorkDir, _ = os.Getwd() +var licenseFile = filepath.Join(currentWorkDir, "LICENSE") func testOpenFile(encoding string, content []byte, t *testing.T) { fi, _ := os.Stat(licenseFile) From e357f6846bd5f07ef3baead76658d4dbb926d5fc Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Wed, 27 Jan 2016 13:30:34 +0800 Subject: [PATCH 39/51] accept @ysqi suggestion --- beego.go | 11 +---------- config.go | 3 +-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/beego.go b/beego.go index 68a76e52..65368295 100644 --- a/beego.go +++ b/beego.go @@ -67,15 +67,6 @@ func Run(params ...string) { } func initBeforeHTTPRun() { - // if AppConfigPath is setted or conf/app.conf exist - /* - err := ParseConfig() - if err != nil { - panic(err) - } - */ - var err error - //init hooks AddAPPStartHook(registerMime) AddAPPStartHook(registerDefaultErrorHandler) @@ -85,7 +76,7 @@ func initBeforeHTTPRun() { AddAPPStartHook(registerAdmin) for _, hk := range hooks { - if err = hk(); err != nil { + if err := hk(); err != nil { panic(err) } } diff --git a/config.go b/config.go index e72f770c..ebc054d6 100644 --- a/config.go +++ b/config.go @@ -20,7 +20,6 @@ import ( "path/filepath" "strings" "fmt" - "errors" "github.com/astaxie/beego/config" "github.com/astaxie/beego/session" @@ -320,7 +319,7 @@ func LoadAppConfig(configPath string, adapterName string) error { } if !utils.FileExists(absConfigPath) { - return errors.New(fmt.Sprintf("the target config file: %s don't exist!", configPath)) + return fmt.Errorf("the target config file: %s don't exist!", configPath) } if absConfigPath == AppConfigPath { From ccce566ba7a41589fb31814b34d6ad50c81dcf9d Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Wed, 27 Jan 2016 16:19:10 +0800 Subject: [PATCH 40/51] accept @astaxie suggestion: change the sequence adapterName and configPath --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index ebc054d6..e0439084 100644 --- a/config.go +++ b/config.go @@ -312,7 +312,7 @@ func parseConfig(appConfigPath string) (err error) { } // LoadAppConfig allow developer to apply a config file -func LoadAppConfig(configPath string, adapterName string) error { +func LoadAppConfig(adapterName string, configPath string) error { absConfigPath, err := filepath.Abs(configPath) if err != nil { return err From 31ef4ae507cf3395cb61dc2c96d5416b7695b3df Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Wed, 27 Jan 2016 16:43:01 +0800 Subject: [PATCH 41/51] rename AppConfigPath, AppConfigProvider to appConfigPath, appConfigProvider, make public to private --- admin.go | 4 ++-- beego.go | 2 +- config.go | 30 +++++++++++++++--------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/admin.go b/admin.go index 3effc582..031e6421 100644 --- a/admin.go +++ b/admin.go @@ -90,8 +90,8 @@ func listConf(rw http.ResponseWriter, r *http.Request) { switch command { case "conf": m := make(map[string]interface{}) - m["AppConfigPath"] = AppConfigPath - m["AppConfigProvider"] = AppConfigProvider + m["AppConfigPath"] = appConfigPath + m["AppConfigProvider"] = appConfigProvider m["BConfig.AppName"] = BConfig.AppName m["BConfig.RunMode"] = BConfig.RunMode m["BConfig.RouterCaseSensitive"] = BConfig.RouterCaseSensitive diff --git a/beego.go b/beego.go index 65368295..fb628e5f 100644 --- a/beego.go +++ b/beego.go @@ -85,7 +85,7 @@ func initBeforeHTTPRun() { // TestBeegoInit is for test package init func TestBeegoInit(ap string) { os.Setenv("BEEGO_RUNMODE", "test") - AppConfigPath = filepath.Join(ap, "conf", "app.conf") + appConfigPath = filepath.Join(ap, "conf", "app.conf") os.Chdir(ap) initBeforeHTTPRun() } diff --git a/config.go b/config.go index e0439084..7e2b3ee7 100644 --- a/config.go +++ b/config.go @@ -106,16 +106,16 @@ var ( AppConfig *beegoAppConfig // AppPath is the absolute path to the app AppPath string - // AppConfigPath is the path to the config files - AppConfigPath string - // AppConfigProvider is the provider for the config, default is ini - AppConfigProvider = "ini" // TemplateCache stores template caching TemplateCache map[string]*template.Template // GlobalSessions is the instance for the session manager GlobalSessions *session.Manager workPath string + // appConfigPath is the path to the config files + appConfigPath string + // appConfigProvider is the provider for the config, default is ini + appConfigProvider = "ini" ) func init() { @@ -187,18 +187,18 @@ func init() { }, } - AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") - if !utils.FileExists(AppConfigPath) { + appConfigPath = filepath.Join(AppPath, "conf", "app.conf") + if !utils.FileExists(appConfigPath) { AppConfig = &beegoAppConfig{config.NewFakeConfig()} return } - parseConfig(AppConfigPath) + parseConfig(appConfigPath) } // now only support ini, next will support json. func parseConfig(appConfigPath string) (err error) { - AppConfig, err = newAppConfig(AppConfigProvider, appConfigPath) + AppConfig, err = newAppConfig(appConfigProvider, appConfigPath) if err != nil { return err } @@ -312,7 +312,7 @@ func parseConfig(appConfigPath string) (err error) { } // LoadAppConfig allow developer to apply a config file -func LoadAppConfig(adapterName string, configPath string) error { +func LoadAppConfig(adapterName, configPath string) error { absConfigPath, err := filepath.Abs(configPath) if err != nil { return err @@ -322,22 +322,22 @@ func LoadAppConfig(adapterName string, configPath string) error { return fmt.Errorf("the target config file: %s don't exist!", configPath) } - if absConfigPath == AppConfigPath { + if absConfigPath == appConfigPath { return nil } - AppConfigPath = absConfigPath - AppConfigProvider = adapterName + appConfigPath = absConfigPath + appConfigProvider = adapterName - return parseConfig(AppConfigPath) + return parseConfig(appConfigPath) } type beegoAppConfig struct { innerConfig config.Configer } -func newAppConfig(AppConfigProvider, AppConfigPath string) (*beegoAppConfig, error) { - ac, err := config.NewConfig(AppConfigProvider, AppConfigPath) +func newAppConfig(appConfigProvider, appConfigPath string) (*beegoAppConfig, error) { + ac, err := config.NewConfig(appConfigProvider, appConfigPath) if err != nil { return nil, err } From 453d744db92323180861705d1d6c35fbb75a4190 Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Wed, 27 Jan 2016 14:58:50 +0100 Subject: [PATCH 42/51] Fix Context.Input.SetParam not overwriting existing value - Also added tests for Context.Input.Param handling --- context/input.go | 7 ++++++ context/input_test.go | 54 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/context/input.go b/context/input.go index c37204bd..edfdf530 100644 --- a/context/input.go +++ b/context/input.go @@ -287,6 +287,13 @@ func (input *BeegoInput) Params() map[string]string { // SetParam will set the param with key and value func (input *BeegoInput) SetParam(key, val string) { + // check if already exists + for i, v := range input.pnames { + if v == key && i <= len(input.pvalues) { + input.pvalues[i] = val + return + } + } input.pvalues = append(input.pvalues, val) input.pnames = append(input.pnames, key) } diff --git a/context/input_test.go b/context/input_test.go index 618e1254..24f6fd99 100644 --- a/context/input_test.go +++ b/context/input_test.go @@ -18,6 +18,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "reflect" "testing" ) @@ -117,3 +118,56 @@ func TestSubDomain(t *testing.T) { t.Fatal("Subdomain parse error, got " + beegoInput.SubDomains()) } } + +func TestParams(t *testing.T) { + inp := NewInput() + + inp.SetParam("p1", "val1_ver1") + inp.SetParam("p2", "val2_ver1") + inp.SetParam("p3", "val3_ver1") + if l := inp.ParamsLen(); l != 3 { + t.Fatalf("Input.ParamsLen wrong value: %d, expected %d", l, 3) + } + + if val := inp.Param("p1"); val != "val1_ver1" { + t.Fatalf("Input.Param wrong value: %s, expected %s", val, "val1_ver1") + } + if val := inp.Param("p3"); val != "val3_ver1" { + t.Fatalf("Input.Param wrong value: %s, expected %s", val, "val3_ver1") + } + vals := inp.Params() + expected := map[string]string{ + "p1": "val1_ver1", + "p2": "val2_ver1", + "p3": "val3_ver1", + } + if !reflect.DeepEqual(vals, expected) { + t.Fatalf("Input.Params wrong value: %s, expected %s", vals, expected) + } + + // overwriting existing params + inp.SetParam("p1", "val1_ver2") + inp.SetParam("p2", "val2_ver2") + expected = map[string]string{ + "p1": "val1_ver2", + "p2": "val2_ver2", + "p3": "val3_ver1", + } + vals = inp.Params() + if !reflect.DeepEqual(vals, expected) { + t.Fatalf("Input.Params wrong value: %s, expected %s", vals, expected) + } + + if l := inp.ParamsLen(); l != 3 { + t.Fatalf("Input.ParamsLen wrong value: %d, expected %d", l, 3) + } + + if val := inp.Param("p1"); val != "val1_ver2" { + t.Fatalf("Input.Param wrong value: %s, expected %s", val, "val1_ver2") + } + + if val := inp.Param("p2"); val != "val2_ver2" { + t.Fatalf("Input.Param wrong value: %s, expected %s", val, "val1_ver2") + } + +} From 7f888e3d18ff735eea10b2b3c6dab91ce90134d1 Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Wed, 27 Jan 2016 19:20:58 +0100 Subject: [PATCH 43/51] Add noColor option for console logger - Also added simple test --- logs/console.go | 7 ++++--- logs/console_test.go | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/logs/console.go b/logs/console.go index 10d8e8b2..871e7972 100644 --- a/logs/console.go +++ b/logs/console.go @@ -47,8 +47,9 @@ var colors = []brush{ // consoleWriter implements LoggerInterface and writes messages to terminal. type consoleWriter struct { - lg *log.Logger - Level int `json:"level"` + lg *log.Logger + Level int `json:"level"` + NoColor bool `json:"noColor"` } // NewConsole create ConsoleWriter returning as LoggerInterface. @@ -75,7 +76,7 @@ func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { return nil } msg = formatLogTime(when) + msg - if runtime.GOOS == "windows" { + if runtime.GOOS == "windows" || c.NoColor { c.lg.Println(msg) return nil } diff --git a/logs/console_test.go b/logs/console_test.go index ce8937d4..45211588 100644 --- a/logs/console_test.go +++ b/logs/console_test.go @@ -42,3 +42,10 @@ func TestConsole(t *testing.T) { log2.SetLogger("console", `{"level":3}`) testConsoleCalls(log2) } + +// Test console without color +func TestConsoleNoColor(t *testing.T) { + log := NewLogger(100) + log.SetLogger("console", `{"noColor":true}`) + testConsoleCalls(log) +} From a0434323982ac73a406177bec245b3286e484378 Mon Sep 17 00:00:00 2001 From: Pelle Johnsen Date: Thu, 28 Jan 2016 07:50:07 +0100 Subject: [PATCH 44/51] Change option name from noColor to color Still same default behavior (with color) --- logs/console.go | 9 +++++---- logs/console_test.go | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/logs/console.go b/logs/console.go index 871e7972..d7ed8d8e 100644 --- a/logs/console.go +++ b/logs/console.go @@ -47,9 +47,9 @@ var colors = []brush{ // consoleWriter implements LoggerInterface and writes messages to terminal. type consoleWriter struct { - lg *log.Logger - Level int `json:"level"` - NoColor bool `json:"noColor"` + lg *log.Logger + Level int `json:"level"` + Color bool `json:"color"` } // NewConsole create ConsoleWriter returning as LoggerInterface. @@ -57,6 +57,7 @@ func NewConsole() Logger { cw := &consoleWriter{ lg: log.New(os.Stdout, "", 0), Level: LevelDebug, + Color: true, } return cw } @@ -76,7 +77,7 @@ func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { return nil } msg = formatLogTime(when) + msg - if runtime.GOOS == "windows" || c.NoColor { + if runtime.GOOS == "windows" || !c.Color { c.lg.Println(msg) return nil } diff --git a/logs/console_test.go b/logs/console_test.go index 45211588..04f2bd7e 100644 --- a/logs/console_test.go +++ b/logs/console_test.go @@ -46,6 +46,6 @@ func TestConsole(t *testing.T) { // Test console without color func TestConsoleNoColor(t *testing.T) { log := NewLogger(100) - log.SetLogger("console", `{"noColor":true}`) + log.SetLogger("console", `{"color":false}`) testConsoleCalls(log) } From 5cd1ed8106bd50d21a641eafd2234b870d7be7df Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 29 Jan 2016 00:01:04 +0800 Subject: [PATCH 45/51] add test for tip --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 30ec5d4b..97444ce6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: go go: + - tip - 1.5.3 - 1.4.3 - 1.3.3 From 0382146c6015b3a4cc482443594f73e45f4abbee Mon Sep 17 00:00:00 2001 From: astaxie Date: Fri, 29 Jan 2016 13:11:11 +0800 Subject: [PATCH 46/51] fix the go vet for go tip --- config.go | 2 +- grace/server.go | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/config.go b/config.go index 7e2b3ee7..ffe92f06 100644 --- a/config.go +++ b/config.go @@ -319,7 +319,7 @@ func LoadAppConfig(adapterName, configPath string) error { } if !utils.FileExists(absConfigPath) { - return fmt.Errorf("the target config file: %s don't exist!", configPath) + return fmt.Errorf("the target config file: %s don't exist", configPath) } if absConfigPath == appConfigPath { diff --git a/grace/server.go b/grace/server.go index f4512ded..101bda56 100644 --- a/grace/server.go +++ b/grace/server.go @@ -90,16 +90,15 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) { addr = ":https" } - config := &tls.Config{} - if srv.TLSConfig != nil { - *config = *srv.TLSConfig + if srv.TLSConfig == nil { + srv.TLSConfig = &tls.Config{} } - if config.NextProtos == nil { - config.NextProtos = []string{"http/1.1"} + if srv.TLSConfig.NextProtos == nil { + srv.TLSConfig.NextProtos = []string{"http/1.1"} } - config.Certificates = make([]tls.Certificate, 1) - config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) + srv.TLSConfig.Certificates = make([]tls.Certificate, 1) + srv.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return } @@ -113,7 +112,7 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) { } srv.tlsInnerListener = newGraceListener(l, srv) - srv.GraceListener = tls.NewListener(srv.tlsInnerListener, config) + srv.GraceListener = tls.NewListener(srv.tlsInnerListener, srv.TLSConfig) if srv.isChild { process, err := os.FindProcess(os.Getppid()) From 09193213a076a0d9cf1784448f8f283acff8a6dd Mon Sep 17 00:00:00 2001 From: astaxie Date: Sun, 31 Jan 2016 23:28:56 +0800 Subject: [PATCH 47/51] add travis hooks --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 97444ce6..3a6c9f84 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,3 +36,5 @@ script: - go vet -x ./... - $HOME/gopath/bin/golint ./... - go test -v ./... +notifications: + webhooks: https://hooks.pubu.im/services/z7m9bvybl3rgtg9 From da38cbfe41171010c88d2227fbd55a80e7721b29 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Mon, 1 Feb 2016 22:39:41 +0800 Subject: [PATCH 48/51] fix issue #1641 --- error.go | 1 + 1 file changed, 1 insertion(+) diff --git a/error.go b/error.go index 94151dd8..4f48fab2 100644 --- a/error.go +++ b/error.go @@ -424,6 +424,7 @@ func exception(errCode string, ctx *context.Context) { func executeError(err *errorInfo, ctx *context.Context, code int) { if err.errorType == errorTypeHandler { + ctx.ResponseWriter.WriteHeader(code) err.handler(ctx.ResponseWriter, ctx.Request) return } From bb50383aa9a84225d902eaaef73df37ba1d26459 Mon Sep 17 00:00:00 2001 From: Thanh Tran Date: Tue, 2 Feb 2016 11:28:43 +0700 Subject: [PATCH 49/51] Add GroupBy to QuerySeter --- orm/types.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/orm/types.go b/orm/types.go index 5fac5fed..469323ff 100644 --- a/orm/types.go +++ b/orm/types.go @@ -148,6 +148,10 @@ type QuerySeter interface { // add OFFSET value // same as Limit function's args[0] Offset(offset interface{}) QuerySeter + // add GROUP BY expression + // for example: + // qs.GroupBy("id") + GroupBy(exprs ...string) QuerySeter // add ORDER expression. // "column" means ASC, "-column" means DESC. // for example: From 4906b600e3a91d2a99accdf8306bc17a7f7784d6 Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 2 Feb 2016 12:43:45 +0800 Subject: [PATCH 50/51] fix the static url with / problem --- template.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/template.go b/template.go index 1b62cf78..7a38630e 100644 --- a/template.go +++ b/template.go @@ -272,7 +272,9 @@ func SetStaticPath(url string, path string) *App { if !strings.HasPrefix(url, "/") { url = "/" + url } - url = strings.TrimRight(url, "/") + if url != "/" { + url = strings.TrimRight(url, "/") + } BConfig.WebConfig.StaticDir[url] = path return BeeApp } @@ -282,7 +284,9 @@ func DelStaticPath(url string) *App { if !strings.HasPrefix(url, "/") { url = "/" + url } - url = strings.TrimRight(url, "/") + if url != "/" { + url = strings.TrimRight(url, "/") + } delete(BConfig.WebConfig.StaticDir, url) return BeeApp } From 2301633d421d0e628463da24263a8dbce5c0480c Mon Sep 17 00:00:00 2001 From: Lei Cao Date: Tue, 2 Feb 2016 23:34:32 +0800 Subject: [PATCH 51/51] Added slack --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fec6113f..6c589584 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ Please see [Documentation](http://beego.me/docs) for more. ## Community * [http://beego.me/community](http://beego.me/community) +* Welcome to join us in Slack: [https://beego.slack.com](https://beego.slack.com), you can get invited from [here](https://github.com/beego/beedoc/issues/232) ## LICENSE