From ecab397073bf1585048849fa74f03084169235f2 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Thu, 28 Jan 2016 21:53:44 +0800 Subject: [PATCH 01/21] try to fix the little bug when calling Close or Flush in async mode --- logs/log.go | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/logs/log.go b/logs/log.go index 2a12ed79..0323e0d3 100644 --- a/logs/log.go +++ b/logs/log.go @@ -98,6 +98,8 @@ type BeeLogger struct { loggerFuncCallDepth int asynchronous bool msgChan chan *logMsg + signalChan chan string + wg sync.WaitGroup outputs []*nameLogger } @@ -122,6 +124,8 @@ func NewLogger(channelLen int64) *BeeLogger { bl.level = LevelDebug bl.loggerFuncCallDepth = 2 bl.msgChan = make(chan *logMsg, channelLen) + bl.signalChan = make(chan string, 1) + bl.wg.Add(1) return bl } @@ -237,6 +241,27 @@ func (bl *BeeLogger) startLogger() { case bm := <-bl.msgChan: bl.writeToLoggers(bm.when, bm.msg, bm.level) logMsgPool.Put(bm) + case sg := <-bl.signalChan: + // Now should only send "flush" or "close" to bl.signalChan + for { + if len(bl.msgChan) > 0 { + bm := <-bl.msgChan + bl.writeToLoggers(bm.when, bm.msg, bm.level) + logMsgPool.Put(bm) + continue + } + break + } + for _, l := range bl.outputs { + l.Flush() + } + if sg == "close" { + for _, l := range bl.outputs { + l.Destroy() + } + bl.outputs = nil + } + bl.wg.Done() } } } @@ -345,27 +370,16 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) { // Flush flush all chan data. func (bl *BeeLogger) Flush() { - for _, l := range bl.outputs { - l.Flush() - } + bl.signalChan <- "flush" + bl.wg.Wait() + bl.wg.Add(1) } // Close close logger, flush all chan data and destroy all adapters in BeeLogger. func (bl *BeeLogger) Close() { - for { - if len(bl.msgChan) > 0 { - bm := <-bl.msgChan - bl.writeToLoggers(bm.when, bm.msg, bm.level) - logMsgPool.Put(bm) - continue - } - break - } - for _, l := range bl.outputs { - l.Flush() - l.Destroy() - } - bl.outputs = nil + bl.signalChan <- "close" + bl.wg.Wait() + bl.wg.Add(1) } func formatLogTime(when time.Time) string { From 5dec3d127cf80851bc7679e7f4880ecdeae553bf Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 2 Feb 2016 16:37:09 +0800 Subject: [PATCH 02/21] colorful console only the terminal supports --- logs/console.go | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/logs/console.go b/logs/console.go index d7ed8d8e..3781e6cd 100644 --- a/logs/console.go +++ b/logs/console.go @@ -47,17 +47,17 @@ var colors = []brush{ // consoleWriter implements LoggerInterface and writes messages to terminal. type consoleWriter struct { - lg *log.Logger - Level int `json:"level"` - Color bool `json:"color"` + lg *log.Logger + Level int `json:"level"` + Colorful bool `json:"color"` //this filed is useful only when system's terminal supports color } // NewConsole create ConsoleWriter returning as LoggerInterface. func NewConsole() Logger { cw := &consoleWriter{ - lg: log.New(os.Stdout, "", 0), - Level: LevelDebug, - Color: true, + lg: log.New(os.Stdout, "", 0), + Level: LevelDebug, + Colorful: true, } return cw } @@ -68,7 +68,11 @@ func (c *consoleWriter) Init(jsonConfig string) error { if len(jsonConfig) == 0 { return nil } - return json.Unmarshal([]byte(jsonConfig), c) + err := json.Unmarshal([]byte(jsonConfig), c) + if runtime.GOOS == "windows" { + c.Colorful = false + } + return err } // WriteMsg write message in console. @@ -77,12 +81,11 @@ func (c *consoleWriter) WriteMsg(when time.Time, msg string, level int) error { return nil } msg = formatLogTime(when) + msg - if runtime.GOOS == "windows" || !c.Color { + if c.Colorful { + c.lg.Println(colors[level](msg)) + } else { c.lg.Println(msg) - return nil } - c.lg.Println(colors[level](msg)) - return nil } From 360220161b31b40f25f0a9eaac8f14b5d5edf46c Mon Sep 17 00:00:00 2001 From: JessonChan Date: Tue, 2 Feb 2016 16:52:53 +0800 Subject: [PATCH 03/21] remove useless var , name style fixed --- config.go | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/config.go b/config.go index ffe92f06..7d7ed2a5 100644 --- a/config.go +++ b/config.go @@ -15,11 +15,11 @@ package beego import ( + "fmt" "html/template" "os" "path/filepath" "strings" - "fmt" "github.com/astaxie/beego/config" "github.com/astaxie/beego/session" @@ -111,7 +111,6 @@ var ( // 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 @@ -120,12 +119,8 @@ var ( func init() { AppPath, _ = filepath.Abs(filepath.Dir(os.Args[0])) - workPath, _ = os.Getwd() - workPath, _ = filepath.Abs(workPath) - if workPath != AppPath { - os.Chdir(AppPath) - } + os.Chdir(AppPath) BConfig = &Config{ AppName: "beego", @@ -175,7 +170,7 @@ func init() { SessionName: "beegosessionID", SessionGCMaxLifetime: 3600, SessionProviderConfig: "", - SessionCookieLifeTime: 0, //set cookie default is the brower life + SessionCookieLifeTime: 0, //set cookie default is the browser life SessionAutoSetCookie: true, SessionDomain: "", }, @@ -189,7 +184,7 @@ func init() { appConfigPath = filepath.Join(AppPath, "conf", "app.conf") if !utils.FileExists(appConfigPath) { - AppConfig = &beegoAppConfig{config.NewFakeConfig()} + AppConfig = &beegoAppConfig{innerConfig: config.NewFakeConfig()} return } @@ -202,11 +197,11 @@ func parseConfig(appConfigPath string) (err error) { if err != nil { return err } - // set the runmode first + // set the run mode first if envRunMode := os.Getenv("BEEGO_RUNMODE"); envRunMode != "" { BConfig.RunMode = envRunMode - } else if runmode := AppConfig.String("RunMode"); runmode != "" { - BConfig.RunMode = runmode + } else if runMode := AppConfig.String("RunMode"); runMode != "" { + BConfig.RunMode = runMode } BConfig.AppName = AppConfig.DefaultString("AppName", BConfig.AppName) @@ -393,46 +388,46 @@ func (b *beegoAppConfig) Float(key string) (float64, error) { return b.innerConfig.Float(key) } -func (b *beegoAppConfig) DefaultString(key string, defaultval string) string { +func (b *beegoAppConfig) DefaultString(key string, defaultVal string) string { if v := b.String(key); v != "" { return v } - return defaultval + return defaultVal } -func (b *beegoAppConfig) DefaultStrings(key string, defaultval []string) []string { +func (b *beegoAppConfig) DefaultStrings(key string, defaultVal []string) []string { if v := b.Strings(key); len(v) != 0 { return v } - return defaultval + return defaultVal } -func (b *beegoAppConfig) DefaultInt(key string, defaultval int) int { +func (b *beegoAppConfig) DefaultInt(key string, defaultVal int) int { if v, err := b.Int(key); err == nil { return v } - return defaultval + return defaultVal } -func (b *beegoAppConfig) DefaultInt64(key string, defaultval int64) int64 { +func (b *beegoAppConfig) DefaultInt64(key string, defaultVal int64) int64 { if v, err := b.Int64(key); err == nil { return v } - return defaultval + return defaultVal } -func (b *beegoAppConfig) DefaultBool(key string, defaultval bool) bool { +func (b *beegoAppConfig) DefaultBool(key string, defaultVal bool) bool { if v, err := b.Bool(key); err == nil { return v } - return defaultval + return defaultVal } -func (b *beegoAppConfig) DefaultFloat(key string, defaultval float64) float64 { +func (b *beegoAppConfig) DefaultFloat(key string, defaultVal float64) float64 { if v, err := b.Float(key); err == nil { return v } - return defaultval + return defaultVal } func (b *beegoAppConfig) DIY(key string) (interface{}, error) { From 2efe7c4c89dc9ca5120f2762db46ce731f265945 Mon Sep 17 00:00:00 2001 From: youngsterxyf Date: Tue, 2 Feb 2016 17:12:47 +0800 Subject: [PATCH 04/21] merge multi commit --- config.go | 4 +-- logs/log.go | 75 +++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/config.go b/config.go index ffe92f06..f9810778 100644 --- a/config.go +++ b/config.go @@ -15,11 +15,11 @@ package beego import ( + "fmt" "html/template" "os" "path/filepath" "strings" - "fmt" "github.com/astaxie/beego/config" "github.com/astaxie/beego/session" @@ -299,7 +299,7 @@ func parseConfig(appConfigPath string) (err error) { } //init log - BeeLogger.Close() + BeeLogger.Reset() for adaptor, config := range BConfig.Log.Outputs { err = BeeLogger.SetLogger(adaptor, config) if err != nil { diff --git a/logs/log.go b/logs/log.go index 0323e0d3..428e8e50 100644 --- a/logs/log.go +++ b/logs/log.go @@ -98,8 +98,8 @@ type BeeLogger struct { loggerFuncCallDepth int asynchronous bool msgChan chan *logMsg - signalChan chan string - wg sync.WaitGroup + signalChan chan string + wg sync.WaitGroup outputs []*nameLogger } @@ -111,7 +111,7 @@ type nameLogger struct { type logMsg struct { level int msg string - when time.Time + when time.Time } var logMsgPool *sync.Pool @@ -125,7 +125,6 @@ func NewLogger(channelLen int64) *BeeLogger { bl.loggerFuncCallDepth = 2 bl.msgChan = make(chan *logMsg, channelLen) bl.signalChan = make(chan string, 1) - bl.wg.Add(1) return bl } @@ -137,6 +136,7 @@ func (bl *BeeLogger) Async() *BeeLogger { return &logMsg{} }, } + bl.wg.Add(1) go bl.startLogger() return bl } @@ -236,6 +236,7 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) { // start logger chan reading. // when chan is not empty, write logs. func (bl *BeeLogger) startLogger() { + gameOver := false for { select { case bm := <-bl.msgChan: @@ -243,26 +244,19 @@ func (bl *BeeLogger) startLogger() { logMsgPool.Put(bm) case sg := <-bl.signalChan: // Now should only send "flush" or "close" to bl.signalChan - for { - if len(bl.msgChan) > 0 { - bm := <-bl.msgChan - bl.writeToLoggers(bm.when, bm.msg, bm.level) - logMsgPool.Put(bm) - continue - } - break - } - for _, l := range bl.outputs { - l.Flush() - } + bl.flush() if sg == "close" { for _, l := range bl.outputs { l.Destroy() } bl.outputs = nil + gameOver = true } bl.wg.Done() } + if gameOver { + break + } } } @@ -370,16 +364,53 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) { // Flush flush all chan data. func (bl *BeeLogger) Flush() { - bl.signalChan <- "flush" - bl.wg.Wait() - bl.wg.Add(1) + if bl.asynchronous { + bl.signalChan <- "flush" + bl.wg.Wait() + bl.wg.Add(1) + return + } + bl.flush() } // Close close logger, flush all chan data and destroy all adapters in BeeLogger. func (bl *BeeLogger) Close() { - bl.signalChan <- "close" - bl.wg.Wait() - bl.wg.Add(1) + if bl.asynchronous { + bl.signalChan <- "close" + bl.wg.Wait() + } else { + bl.flush() + for _, l := range bl.outputs { + l.Destroy() + } + bl.outputs = nil + } + close(bl.msgChan) + close(bl.signalChan) +} + +// Reset close all outputs, and set bl.outputs to nil +func (bl *BeeLogger) Reset() { + bl.Flush() + for _, l := range bl.outputs { + l.Destroy() + } + bl.outputs = nil +} + +func (bl *BeeLogger) flush() { + for { + if len(bl.msgChan) > 0 { + bm := <-bl.msgChan + bl.writeToLoggers(bm.when, bm.msg, bm.level) + logMsgPool.Put(bm) + continue + } + break + } + for _, l := range bl.outputs { + l.Flush() + } } func formatLogTime(when time.Time) string { From 9411063574444ae932d1e0731cad965f2fc9b06a Mon Sep 17 00:00:00 2001 From: ysqi Date: Fri, 12 Feb 2016 14:45:45 +0800 Subject: [PATCH 05/21] fix #1595 --- tree.go | 9 ++++----- tree_test.go | 12 ++++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tree.go b/tree.go index 761ae0ce..594e9999 100644 --- a/tree.go +++ b/tree.go @@ -265,15 +265,14 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, } t.wildcard.addseg(segments[1:], route, append(wildcards, params...), reg+regexpStr) } else { - var ok bool var subTree *Tree - for _, subTree = range t.fixrouters { - if t.prefix == seg { - ok = true + for _, sub := range t.fixrouters { + if sub.prefix == seg { + subTree = sub break } } - if !ok { + if subTree == nil { subTree = NewTree() subTree.prefix = seg t.fixrouters = append(t.fixrouters, subTree) diff --git a/tree_test.go b/tree_test.go index 9f21c18c..531df046 100644 --- a/tree_test.go +++ b/tree_test.go @@ -221,6 +221,18 @@ func TestAddTree4(t *testing.T) { } } +// Test for issue #1595 +func TestAddTree5(t *testing.T) { + tr := NewTree() + tr.AddRouter("/v1/shop/:id", "shopdetail") + tr.AddRouter("/v1/shop/", "shophome") + ctx := context.NewContext() + obj := tr.Match("/v1/shop/", ctx) + if obj == nil || obj.(string) != "shophome" { + t.Fatal("url /v1/shop/ need match router /v1/shop/ ") + } +} + func TestSplitPath(t *testing.T) { a := splitPath("") if len(a) != 0 { From d5f07d65bb55f6b77390ec4aa1da5229d28653b9 Mon Sep 17 00:00:00 2001 From: ysqi Date: Sun, 14 Feb 2016 18:54:40 +0800 Subject: [PATCH 06/21] panic parse config error --- config.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.go b/config.go index ffe92f06..92fb8914 100644 --- a/config.go +++ b/config.go @@ -193,7 +193,9 @@ func init() { return } - parseConfig(appConfigPath) + if err := parseConfig(appConfigPath); err != nil { + panic(err) + } } // now only support ini, next will support json. From 891016a0a25cdda21b119d07972bddf0a2f995ea Mon Sep 17 00:00:00 2001 From: ysqi Date: Sun, 14 Feb 2016 18:55:42 +0800 Subject: [PATCH 07/21] ignore parse include config file error --- config/ini.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/config/ini.go b/config/ini.go index da6f2b3a..2cec7baa 100644 --- a/config/ini.go +++ b/config/ini.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "io/ioutil" + "log" "os" "path" "strconv" @@ -134,7 +135,9 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) { } i, err := ini.parseFile(otherfile) if err != nil { - return nil, err + // ignore error + log.Printf("[warn] handle config %q error, %s \n", key, err.Error()) + continue } for sec, dt := range i.data { if _, ok := cfg.data[sec]; !ok { From 3da28535fe5aae6f0515cfb8c13b13041ac2d1d6 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Thu, 25 Feb 2016 17:37:28 +0800 Subject: [PATCH 08/21] lock the templates map when goroutie update the map --- template.go | 98 ++++++++++++++++++++++++++--------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/template.go b/template.go index 7a38630e..9954cf32 100644 --- a/template.go +++ b/template.go @@ -23,6 +23,7 @@ import ( "path/filepath" "regexp" "strings" + "sync" "github.com/astaxie/beego/utils" ) @@ -30,7 +31,8 @@ import ( var ( beegoTplFuncMap = make(template.FuncMap) // BeeTemplates caching map and supported template file extensions. - BeeTemplates = make(map[string]*template.Template) + BeeTemplates = make(map[string]*template.Template) + templatesLock sync.Mutex // BeeTemplateExt stores the template extension which will build BeeTemplateExt = []string{"tpl", "html"} ) @@ -66,17 +68,21 @@ func init() { } // AddFuncMap let user to register a func in the template. -func AddFuncMap(key string, funname interface{}) error { - beegoTplFuncMap[key] = funname +func AddFuncMap(key string, fn interface{}) error { + beegoTplFuncMap[key] = fn return nil } -type templatefile struct { +type templateFile struct { root string files map[string][]string } -func (tf *templatefile) visit(paths string, f os.FileInfo, err error) error { +// visit will make the paths into two part,the first is subDir (without tf.root),the second is full path(without tf.root). +// if tf.root="views" and +// paths is "views/errors/404.html",the subDir will be "errors",the file will be "errors/404.html" +// paths is "views/admin/errors/404.html",the subDir will be "admin/errors",the file will be "admin/errors/404.html" +func (tf *templateFile) visit(paths string, f os.FileInfo, err error) error { if f == nil { return err } @@ -88,18 +94,10 @@ func (tf *templatefile) visit(paths string, f os.FileInfo, err error) error { } replace := strings.NewReplacer("\\", "/") - a := []byte(paths) - a = a[len([]byte(tf.root)):] - file := strings.TrimLeft(replace.Replace(string(a)), "/") - subdir := filepath.Dir(file) - if _, ok := tf.files[subdir]; ok { - tf.files[subdir] = append(tf.files[subdir], file) - } else { - m := make([]string, 1) - m[0] = file - tf.files[subdir] = m - } + file := strings.TrimLeft(replace.Replace(paths[len(tf.root):]), "/") + subDir := filepath.Dir(file) + tf.files[subDir] = append(tf.files[subDir], file) return nil } @@ -132,7 +130,7 @@ func BuildTemplate(dir string, files ...string) error { } return errors.New("dir open err") } - self := &templatefile{ + self := &templateFile{ root: dir, files: make(map[string][]string), } @@ -146,12 +144,14 @@ func BuildTemplate(dir string, files ...string) error { for _, v := range self.files { for _, file := range v { if len(files) == 0 || utils.InSlice(file, files) { + templatesLock.Lock() t, err := getTemplate(self.root, file, v...) if err != nil { Trace("parse template err:", file, err) } else { BeeTemplates[file] = t } + templatesLock.Unlock() } } } @@ -159,16 +159,16 @@ func BuildTemplate(dir string, files ...string) error { } func getTplDeep(root, file, parent string, t *template.Template) (*template.Template, [][]string, error) { - var fileabspath string + var fileAbsPath string if filepath.HasPrefix(file, "../") { - fileabspath = filepath.Join(root, filepath.Dir(parent), file) + fileAbsPath = filepath.Join(root, filepath.Dir(parent), file) } else { - fileabspath = filepath.Join(root, file) + fileAbsPath = filepath.Join(root, file) } - if e := utils.FileExists(fileabspath); !e { + if e := utils.FileExists(fileAbsPath); !e { panic("can't find template file:" + file) } - data, err := ioutil.ReadFile(fileabspath) + data, err := ioutil.ReadFile(fileAbsPath) if err != nil { return nil, [][]string{}, err } @@ -177,11 +177,11 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp return nil, [][]string{}, err } reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*template[ ]+\"([^\"]+)\"") - allsub := reg.FindAllStringSubmatch(string(data), -1) - for _, m := range allsub { + allSub := reg.FindAllStringSubmatch(string(data), -1) + for _, m := range allSub { if len(m) == 2 { - tlook := t.Lookup(m[1]) - if tlook != nil { + tl := t.Lookup(m[1]) + if tl != nil { continue } if !HasTemplateExt(m[1]) { @@ -193,17 +193,17 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp } } } - return t, allsub, nil + return t, allSub, nil } func getTemplate(root, file string, others ...string) (t *template.Template, err error) { t = template.New(file).Delims(BConfig.WebConfig.TemplateLeft, BConfig.WebConfig.TemplateRight).Funcs(beegoTplFuncMap) - var submods [][]string - t, submods, err = getTplDeep(root, file, "", t) + var subMods [][]string + t, subMods, err = getTplDeep(root, file, "", t) if err != nil { return nil, err } - t, err = _getTemplate(t, root, submods, others...) + t, err = _getTemplate(t, root, subMods, others...) if err != nil { return nil, err @@ -211,44 +211,44 @@ func getTemplate(root, file string, others ...string) (t *template.Template, err return } -func _getTemplate(t0 *template.Template, root string, submods [][]string, others ...string) (t *template.Template, err error) { +func _getTemplate(t0 *template.Template, root string, subMods [][]string, others ...string) (t *template.Template, err error) { t = t0 - for _, m := range submods { + for _, m := range subMods { if len(m) == 2 { - templ := t.Lookup(m[1]) - if templ != nil { + tpl := t.Lookup(m[1]) + if tpl != nil { continue } //first check filename - for _, otherfile := range others { - if otherfile == m[1] { - var submods1 [][]string - t, submods1, err = getTplDeep(root, otherfile, "", t) + for _, otherFile := range others { + if otherFile == m[1] { + var subMods1 [][]string + t, subMods1, err = getTplDeep(root, otherFile, "", t) if err != nil { Trace("template parse file err:", err) - } else if submods1 != nil && len(submods1) > 0 { - t, err = _getTemplate(t, root, submods1, others...) + } else if subMods1 != nil && len(subMods1) > 0 { + t, err = _getTemplate(t, root, subMods1, others...) } break } } //second check define - for _, otherfile := range others { - fileabspath := filepath.Join(root, otherfile) - data, err := ioutil.ReadFile(fileabspath) + for _, otherFile := range others { + fileAbsPath := filepath.Join(root, otherFile) + data, err := ioutil.ReadFile(fileAbsPath) if err != nil { continue } reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*define[ ]+\"([^\"]+)\"") - allsub := reg.FindAllStringSubmatch(string(data), -1) - for _, sub := range allsub { + allSub := reg.FindAllStringSubmatch(string(data), -1) + for _, sub := range allSub { if len(sub) == 2 && sub[1] == m[1] { - var submods1 [][]string - t, submods1, err = getTplDeep(root, otherfile, "", t) + var subMods1 [][]string + t, subMods1, err = getTplDeep(root, otherFile, "", t) if err != nil { Trace("template parse file err:", err) - } else if submods1 != nil && len(submods1) > 0 { - t, err = _getTemplate(t, root, submods1, others...) + } else if subMods1 != nil && len(subMods1) > 0 { + t, err = _getTemplate(t, root, subMods1, others...) } break } From ffbb45e567a7616540f0dfdfaeeeffd7617b53d4 Mon Sep 17 00:00:00 2001 From: ysqi Date: Sat, 27 Feb 2016 20:18:59 +0800 Subject: [PATCH 09/21] Revert "ignore parse include config file error" This reverts commit 891016a0a25cdda21b119d07972bddf0a2f995ea. --- config/ini.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/config/ini.go b/config/ini.go index 2cec7baa..da6f2b3a 100644 --- a/config/ini.go +++ b/config/ini.go @@ -21,7 +21,6 @@ import ( "fmt" "io" "io/ioutil" - "log" "os" "path" "strconv" @@ -135,9 +134,7 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) { } i, err := ini.parseFile(otherfile) if err != nil { - // ignore error - log.Printf("[warn] handle config %q error, %s \n", key, err.Error()) - continue + return nil, err } for sec, dt := range i.data { if _, ok := cfg.data[sec]; !ok { From 477de9a3f3f37a608c225b4e4addb18f183d87ca Mon Sep 17 00:00:00 2001 From: iexploree Date: Tue, 1 Mar 2016 10:51:47 +0800 Subject: [PATCH 10/21] fix bug: session id undecoded when destroy and sesssion memory provider push wrong --- session/sess_mem.go | 6 ++++-- session/session.go | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/session/sess_mem.go b/session/sess_mem.go index dd61ef57..8d75d2c6 100644 --- a/session/sess_mem.go +++ b/session/sess_mem.go @@ -102,7 +102,8 @@ func (pder *MemProvider) SessionRead(sid string) (Store, error) { pder.lock.RUnlock() pder.lock.Lock() newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})} - element := pder.list.PushBack(newsess) + // fix bug: new session should be pushed into the head of list(more fresh) + element := pder.list.PushFront(newsess) pder.sessions[sid] = element pder.lock.Unlock() return newsess, nil @@ -134,7 +135,8 @@ func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (Store, error) { pder.lock.RUnlock() pder.lock.Lock() newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})} - element := pder.list.PushBack(newsess) + // fix bug: new session should be pushed into the head of list(more fresh) + element := pder.list.PushFront(newsess) pder.sessions[sid] = element pder.lock.Unlock() return newsess, nil diff --git a/session/session.go b/session/session.go index 39d475fc..4c422906 100644 --- a/session/session.go +++ b/session/session.go @@ -201,7 +201,9 @@ func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { if err != nil || cookie.Value == "" { return } - manager.provider.SessionDestroy(cookie.Value) + // fix bug: cookie.Value has been urlencoded, so should be decoded here + sid, _ := url.QueryUnescape(cookie.Value) + manager.provider.SessionDestroy(sid) if manager.config.EnableSetCookie { expiration := time.Now() cookie = &http.Cookie{Name: manager.config.CookieName, From a144f117a3ecefe54ec5fd16f3229c47a988ca2b Mon Sep 17 00:00:00 2001 From: iexploree Date: Tue, 1 Mar 2016 13:39:36 +0800 Subject: [PATCH 11/21] remove comment --- session/sess_mem.go | 2 -- session/session.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/session/sess_mem.go b/session/sess_mem.go index 8d75d2c6..64d8b056 100644 --- a/session/sess_mem.go +++ b/session/sess_mem.go @@ -102,7 +102,6 @@ func (pder *MemProvider) SessionRead(sid string) (Store, error) { pder.lock.RUnlock() pder.lock.Lock() newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})} - // fix bug: new session should be pushed into the head of list(more fresh) element := pder.list.PushFront(newsess) pder.sessions[sid] = element pder.lock.Unlock() @@ -135,7 +134,6 @@ func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (Store, error) { pder.lock.RUnlock() pder.lock.Lock() newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})} - // fix bug: new session should be pushed into the head of list(more fresh) element := pder.list.PushFront(newsess) pder.sessions[sid] = element pder.lock.Unlock() diff --git a/session/session.go b/session/session.go index 4c422906..9fe99a17 100644 --- a/session/session.go +++ b/session/session.go @@ -201,7 +201,7 @@ func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) { if err != nil || cookie.Value == "" { return } - // fix bug: cookie.Value has been urlencoded, so should be decoded here + sid, _ := url.QueryUnescape(cookie.Value) manager.provider.SessionDestroy(sid) if manager.config.EnableSetCookie { From f0dcaa7f8484f91c984fa094c8cb87a4bd6da314 Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 1 Mar 2016 16:43:56 +0800 Subject: [PATCH 12/21] remove couchbase dependence --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3a6c9f84..3321424e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,6 @@ install: - go get github.com/beego/x2j - go get github.com/beego/goyaml2 - go get github.com/belogik/goes - - go get github.com/couchbase/go-couchbase - go get github.com/siddontang/ledisdb/config - go get github.com/siddontang/ledisdb/ledis - go get golang.org/x/tools/cmd/vet From d81a768802356f9ca62efdd8af8d3289bebd5c8b Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 1 Mar 2016 16:54:37 +0800 Subject: [PATCH 13/21] change couchbase to beego/go-couchbase --- .travis.yml | 1 + session/couchbase/sess_couchbase.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3321424e..5b754b9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ install: - go get github.com/bradfitz/gomemcache/memcache - go get github.com/garyburd/redigo/redis - go get github.com/beego/x2j + - go get github.com/beego/go-couchbase - go get github.com/beego/goyaml2 - go get github.com/belogik/goes - go get github.com/siddontang/ledisdb/config diff --git a/session/couchbase/sess_couchbase.go b/session/couchbase/sess_couchbase.go index d5be11d0..2cf14454 100644 --- a/session/couchbase/sess_couchbase.go +++ b/session/couchbase/sess_couchbase.go @@ -37,7 +37,7 @@ import ( "strings" "sync" - couchbase "github.com/couchbase/go-couchbase" + couchbase "github.com/beego/go-couchbase" "github.com/astaxie/beego/session" ) From 36e31609043ff0971896792b3721ae79759423c8 Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 1 Mar 2016 21:41:44 +0800 Subject: [PATCH 14/21] add go1.6.0 and remove 1.3.3 --- .travis.yml | 4 ++-- session/couchbase/sess_couchbase.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b754b9c..380eca81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,9 @@ language: go go: - tip + - 1.6.0 - 1.5.3 - 1.4.3 - - 1.3.3 services: - redis-server - mysql @@ -21,7 +21,7 @@ install: - go get github.com/bradfitz/gomemcache/memcache - go get github.com/garyburd/redigo/redis - go get github.com/beego/x2j - - go get github.com/beego/go-couchbase + - go get github.com/couchbase/go-couchbase - go get github.com/beego/goyaml2 - go get github.com/belogik/goes - go get github.com/siddontang/ledisdb/config diff --git a/session/couchbase/sess_couchbase.go b/session/couchbase/sess_couchbase.go index 2cf14454..d5be11d0 100644 --- a/session/couchbase/sess_couchbase.go +++ b/session/couchbase/sess_couchbase.go @@ -37,7 +37,7 @@ import ( "strings" "sync" - couchbase "github.com/beego/go-couchbase" + couchbase "github.com/couchbase/go-couchbase" "github.com/astaxie/beego/session" ) From 8ff74e71cbd61556878fd822e23ba061de6bb841 Mon Sep 17 00:00:00 2001 From: ysqi Date: Wed, 2 Mar 2016 22:44:20 +0800 Subject: [PATCH 15/21] Fixed #1735 Return empty []string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need return empty []string if config value is empty. split `“”` ==> []string{}, Not []string{“”} --- config/ini.go | 6 +++++- config/ini_test.go | 1 + config/xml/xml.go | 6 +++++- config/xml/xml_test.go | 3 +++ config/yaml/yaml.go | 6 +++++- config/yaml/yaml_test.go | 4 ++++ 6 files changed, 23 insertions(+), 3 deletions(-) diff --git a/config/ini.go b/config/ini.go index da6f2b3a..a690ede0 100644 --- a/config/ini.go +++ b/config/ini.go @@ -270,7 +270,11 @@ func (c *IniConfigContainer) DefaultString(key string, defaultval string) string // Strings returns the []string value for a given key. func (c *IniConfigContainer) Strings(key string) []string { - return strings.Split(c.String(key), ";") + v := c.String(key) + if v == "" { + return []string{} + } + return strings.Split(v, ";") } // DefaultStrings returns the []string value for a given key. diff --git a/config/ini_test.go b/config/ini_test.go index 11063d99..93fce61f 100644 --- a/config/ini_test.go +++ b/config/ini_test.go @@ -71,6 +71,7 @@ peers = one;two;three "null": "", "demo2::key1": "", "error": "", + "emptystrings": []string{}, } ) diff --git a/config/xml/xml.go b/config/xml/xml.go index ffb32862..2757b0bc 100644 --- a/config/xml/xml.go +++ b/config/xml/xml.go @@ -174,7 +174,11 @@ func (c *ConfigContainer) DefaultString(key string, defaultval string) string { // Strings returns the []string value for a given key. func (c *ConfigContainer) Strings(key string) []string { - return strings.Split(c.String(key), ";") + v := c.String(key) + if v == "" { + return []string{} + } + return strings.Split(v, ";") } // DefaultStrings returns the []string value for a given key. diff --git a/config/xml/xml_test.go b/config/xml/xml_test.go index fa3c17f1..308e257d 100644 --- a/config/xml/xml_test.go +++ b/config/xml/xml_test.go @@ -82,4 +82,7 @@ func TestXML(t *testing.T) { if xmlconf.String("name") != "astaxie" { t.Fatal("get name error") } + if len(xmlconf.Strings("emptystrings")) != 0 { + t.Fatal("get emtpy strings error") + } } diff --git a/config/yaml/yaml.go b/config/yaml/yaml.go index 9a96ac92..9a4fb2e9 100644 --- a/config/yaml/yaml.go +++ b/config/yaml/yaml.go @@ -211,7 +211,11 @@ func (c *ConfigContainer) DefaultString(key string, defaultval string) string { // Strings returns the []string value for a given key. func (c *ConfigContainer) Strings(key string) []string { - return strings.Split(c.String(key), ";") + v := c.String(key) + if v == "" { + return []string{} + } + return strings.Split(v, ";") } // DefaultStrings returns the []string value for a given key. diff --git a/config/yaml/yaml_test.go b/config/yaml/yaml_test.go index 19ecdca1..3bbaaa32 100644 --- a/config/yaml/yaml_test.go +++ b/config/yaml/yaml_test.go @@ -79,4 +79,8 @@ func TestYaml(t *testing.T) { if yamlconf.String("name") != "astaxie" { t.Fatal("get name error") } + + if len(yamlconf.Strings("emptystrings")) != 0 { + t.Fatal("get emtpy strings error") + } } From 19d921d3f51321851ec1f301b56748f5e209077b Mon Sep 17 00:00:00 2001 From: ysqi Date: Thu, 3 Mar 2016 20:03:23 +0800 Subject: [PATCH 16/21] Return nil not empty []string{} Return nil if config value does not exist or is empty --- config/fake.go | 8 ++++++-- config/ini.go | 5 +++-- config/json.go | 4 ++-- config/xml/xml.go | 4 ++-- config/xml/xml_test.go | 2 +- config/yaml/yaml.go | 4 ++-- config/yaml/yaml_test.go | 2 +- 7 files changed, 17 insertions(+), 12 deletions(-) diff --git a/config/fake.go b/config/fake.go index 6daaca2c..7e362608 100644 --- a/config/fake.go +++ b/config/fake.go @@ -46,12 +46,16 @@ func (c *fakeConfigContainer) DefaultString(key string, defaultval string) strin } func (c *fakeConfigContainer) Strings(key string) []string { - return strings.Split(c.getData(key), ";") + v := c.getData(key) + if v == "" { + return nil + } + return strings.Split(v, ";") } func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string { v := c.Strings(key) - if len(v) == 0 { + if v == nil { return defaultval } return v diff --git a/config/ini.go b/config/ini.go index a690ede0..9c19b9b1 100644 --- a/config/ini.go +++ b/config/ini.go @@ -269,10 +269,11 @@ func (c *IniConfigContainer) DefaultString(key string, defaultval string) string } // Strings returns the []string value for a given key. +// Return nil if config value does not exist or is empty. func (c *IniConfigContainer) Strings(key string) []string { v := c.String(key) if v == "" { - return []string{} + return nil } return strings.Split(v, ";") } @@ -281,7 +282,7 @@ func (c *IniConfigContainer) Strings(key string) []string { // if err != nil return defaltval func (c *IniConfigContainer) DefaultStrings(key string, defaultval []string) []string { v := c.Strings(key) - if len(v) == 0 { + if v == nil { return defaultval } return v diff --git a/config/json.go b/config/json.go index 0bc1d456..fce517eb 100644 --- a/config/json.go +++ b/config/json.go @@ -173,7 +173,7 @@ func (c *JSONConfigContainer) DefaultString(key string, defaultval string) strin func (c *JSONConfigContainer) Strings(key string) []string { stringVal := c.String(key) if stringVal == "" { - return []string{} + return nil } return strings.Split(c.String(key), ";") } @@ -181,7 +181,7 @@ func (c *JSONConfigContainer) Strings(key string) []string { // DefaultStrings returns the []string value for a given key. // if err != nil return defaltval func (c *JSONConfigContainer) DefaultStrings(key string, defaultval []string) []string { - if v := c.Strings(key); len(v) > 0 { + if v := c.Strings(key); v != nil { return v } return defaultval diff --git a/config/xml/xml.go b/config/xml/xml.go index 2757b0bc..b5291bf4 100644 --- a/config/xml/xml.go +++ b/config/xml/xml.go @@ -176,7 +176,7 @@ func (c *ConfigContainer) DefaultString(key string, defaultval string) string { func (c *ConfigContainer) Strings(key string) []string { v := c.String(key) if v == "" { - return []string{} + return nil } return strings.Split(v, ";") } @@ -185,7 +185,7 @@ func (c *ConfigContainer) Strings(key string) []string { // if err != nil return defaltval func (c *ConfigContainer) DefaultStrings(key string, defaultval []string) []string { v := c.Strings(key) - if len(v) == 0 { + if v == nil { return defaultval } return v diff --git a/config/xml/xml_test.go b/config/xml/xml_test.go index 308e257d..60dcba54 100644 --- a/config/xml/xml_test.go +++ b/config/xml/xml_test.go @@ -82,7 +82,7 @@ func TestXML(t *testing.T) { if xmlconf.String("name") != "astaxie" { t.Fatal("get name error") } - if len(xmlconf.Strings("emptystrings")) != 0 { + if xmlconf.Strings("emptystrings") != nil { t.Fatal("get emtpy strings error") } } diff --git a/config/yaml/yaml.go b/config/yaml/yaml.go index 9a4fb2e9..7e1d0426 100644 --- a/config/yaml/yaml.go +++ b/config/yaml/yaml.go @@ -213,7 +213,7 @@ func (c *ConfigContainer) DefaultString(key string, defaultval string) string { func (c *ConfigContainer) Strings(key string) []string { v := c.String(key) if v == "" { - return []string{} + return nil } return strings.Split(v, ";") } @@ -222,7 +222,7 @@ func (c *ConfigContainer) Strings(key string) []string { // if err != nil return defaltval func (c *ConfigContainer) DefaultStrings(key string, defaultval []string) []string { v := c.Strings(key) - if len(v) == 0 { + if v == nil { return defaultval } return v diff --git a/config/yaml/yaml_test.go b/config/yaml/yaml_test.go index 3bbaaa32..80cbb8fe 100644 --- a/config/yaml/yaml_test.go +++ b/config/yaml/yaml_test.go @@ -80,7 +80,7 @@ func TestYaml(t *testing.T) { t.Fatal("get name error") } - if len(yamlconf.Strings("emptystrings")) != 0 { + if yamlconf.Strings("emptystrings") != nil { t.Fatal("get emtpy strings error") } } From 226e54e0d8d81b287a67949d9559572be5ccc363 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 4 Mar 2016 10:15:59 +0800 Subject: [PATCH 17/21] static file map race bug fixed --- staticfile.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/staticfile.go b/staticfile.go index 9534ce91..0aad2c81 100644 --- a/staticfile.go +++ b/staticfile.go @@ -93,12 +93,14 @@ type serveContentHolder struct { var ( staticFileMap = make(map[string]*serveContentHolder) - mapLock sync.Mutex + mapLock sync.RWMutex ) func openFile(filePath string, fi os.FileInfo, acceptEncoding string) (bool, string, *serveContentHolder, error) { mapKey := acceptEncoding + ":" + filePath + mapLock.RLock() mapFile, _ := staticFileMap[mapKey] + mapLock.RUnlock() if isOk(mapFile, fi) { return mapFile.encoding != "", mapFile.encoding, mapFile, nil } From 8bd1be8e29d210ecb54099180c6059ce06718812 Mon Sep 17 00:00:00 2001 From: FlamingTree Date: Fri, 4 Mar 2016 11:16:47 +0800 Subject: [PATCH 18/21] Update validators.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加178号段 --- validation/validators.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validation/validators.go b/validation/validators.go index ebff2191..9b04c5ce 100644 --- a/validation/validators.go +++ b/validation/validators.go @@ -588,7 +588,7 @@ func (b Base64) GetLimitValue() interface{} { } // just for chinese mobile phone number -var mobilePattern = regexp.MustCompile("^((\\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][0679]|[4][579]))\\d{8}$") +var mobilePattern = regexp.MustCompile("^((\\+86)|(86))?(1(([35][0-9])|[8][0-9]|[7][06789]|[4][579]))\\d{8}$") // Mobile check struct type Mobile struct { From 1f46c1d231dfe36543e99d3a28ceb87b0fefae4a Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 4 Mar 2016 12:00:43 +0800 Subject: [PATCH 19/21] add template read lock when dev mode --- controller.go | 33 ++++++++++++++++++--------------- template.go | 27 +++++++++++++++++---------- template_test.go | 8 ++++---- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/controller.go b/controller.go index a2943d42..54da81ec 100644 --- a/controller.go +++ b/controller.go @@ -199,6 +199,7 @@ func (c *Controller) RenderString() (string, error) { func (c *Controller) RenderBytes() ([]byte, error) { //if the controller has set layout, then first get the tplname's content set the content to the layout var buf bytes.Buffer + var err error if c.Layout != "" { if c.TplName == "" { c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt @@ -216,13 +217,14 @@ func (c *Controller) RenderBytes() ([]byte, error) { } BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...) } - if _, ok := BeeTemplates[c.TplName]; !ok { + if t := getTemplateByName(c.TplName); t == nil { panic("can't find templatefile in the path:" + c.TplName) - } - err := BeeTemplates[c.TplName].ExecuteTemplate(&buf, c.TplName, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err + } else { + err = t.ExecuteTemplate(&buf, c.TplName, c.Data) + if err != nil { + Trace("template Execute err:", err) + return nil, err + } } c.Data["LayoutContent"] = template.HTML(buf.String()) @@ -234,7 +236,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { } buf.Reset() - err = BeeTemplates[sectionTpl].ExecuteTemplate(&buf, sectionTpl, c.Data) + err = getTemplateByName(sectionTpl).ExecuteTemplate(&buf, sectionTpl, c.Data) if err != nil { Trace("template Execute err:", err) return nil, err @@ -244,7 +246,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { } buf.Reset() - err = BeeTemplates[c.Layout].ExecuteTemplate(&buf, c.Layout, c.Data) + err = getTemplateByName(c.Layout).ExecuteTemplate(&buf, c.Layout, c.Data) if err != nil { Trace("template Execute err:", err) return nil, err @@ -258,14 +260,15 @@ func (c *Controller) RenderBytes() ([]byte, error) { if BConfig.RunMode == DEV { BuildTemplate(BConfig.WebConfig.ViewsPath, c.TplName) } - if _, ok := BeeTemplates[c.TplName]; !ok { + if t := getTemplateByName(c.TplName); t == nil { panic("can't find templatefile in the path:" + c.TplName) - } - buf.Reset() - err := BeeTemplates[c.TplName].ExecuteTemplate(&buf, c.TplName, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err + } else { + buf.Reset() + err = t.ExecuteTemplate(&buf, c.TplName, c.Data) + if err != nil { + Trace("template Execute err:", err) + return nil, err + } } return buf.Bytes(), nil } diff --git a/template.go b/template.go index 9954cf32..da79d383 100644 --- a/template.go +++ b/template.go @@ -30,13 +30,21 @@ import ( var ( beegoTplFuncMap = make(template.FuncMap) - // BeeTemplates caching map and supported template file extensions. - BeeTemplates = make(map[string]*template.Template) - templatesLock sync.Mutex - // BeeTemplateExt stores the template extension which will build - BeeTemplateExt = []string{"tpl", "html"} + // beeTemplates caching map and supported template file extensions. + beeTemplates = make(map[string]*template.Template) + templatesLock sync.RWMutex + // beeTemplateExt stores the template extension which will build + beeTemplateExt = []string{"tpl", "html"} ) +func getTemplateByName(name string) *template.Template { + if BConfig.RunMode == "dev" { + templatesLock.RLock() + defer templatesLock.RUnlock() + } + return beeTemplates[name] +} + func init() { beegoTplFuncMap["dateformat"] = DateFormat beegoTplFuncMap["date"] = Date @@ -55,7 +63,6 @@ func init() { beegoTplFuncMap["config"] = GetConfig beegoTplFuncMap["map_get"] = MapGet - // go1.2 added template funcs // Comparisons beegoTplFuncMap["eq"] = eq // == beegoTplFuncMap["ge"] = ge // >= @@ -103,7 +110,7 @@ func (tf *templateFile) visit(paths string, f os.FileInfo, err error) error { // HasTemplateExt return this path contains supported template extension of beego or not. func HasTemplateExt(paths string) bool { - for _, v := range BeeTemplateExt { + for _, v := range beeTemplateExt { if strings.HasSuffix(paths, "."+v) { return true } @@ -113,12 +120,12 @@ func HasTemplateExt(paths string) bool { // AddTemplateExt add new extension for template. func AddTemplateExt(ext string) { - for _, v := range BeeTemplateExt { + for _, v := range beeTemplateExt { if v == ext { return } } - BeeTemplateExt = append(BeeTemplateExt, ext) + beeTemplateExt = append(beeTemplateExt, ext) } // BuildTemplate will build all template files in a directory. @@ -149,7 +156,7 @@ func BuildTemplate(dir string, files ...string) error { if err != nil { Trace("parse template err:", file, err) } else { - BeeTemplates[file] = t + beeTemplates[file] = t } templatesLock.Unlock() } diff --git a/template_test.go b/template_test.go index 2e222efc..4f13736c 100644 --- a/template_test.go +++ b/template_test.go @@ -70,10 +70,10 @@ func TestTemplate(t *testing.T) { if err := BuildTemplate(dir); err != nil { t.Fatal(err) } - if len(BeeTemplates) != 3 { - t.Fatalf("should be 3 but got %v", len(BeeTemplates)) + if len(beeTemplates) != 3 { + t.Fatalf("should be 3 but got %v", len(beeTemplates)) } - if err := BeeTemplates["index.tpl"].ExecuteTemplate(os.Stdout, "index.tpl", nil); err != nil { + if err := beeTemplates["index.tpl"].ExecuteTemplate(os.Stdout, "index.tpl", nil); err != nil { t.Fatal(err) } for _, name := range files { @@ -126,7 +126,7 @@ func TestRelativeTemplate(t *testing.T) { if err := BuildTemplate(dir, files[1]); err != nil { t.Fatal(err) } - if err := BeeTemplates["easyui/rbac/user.tpl"].ExecuteTemplate(os.Stdout, "easyui/rbac/user.tpl", nil); err != nil { + if err := beeTemplates["easyui/rbac/user.tpl"].ExecuteTemplate(os.Stdout, "easyui/rbac/user.tpl", nil); err != nil { t.Fatal(err) } for _, name := range files { From 6747c55a8115486e6fd7884e4773739cdb402a60 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 4 Mar 2016 12:01:04 +0800 Subject: [PATCH 20/21] remove unused cache --- config.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/config.go b/config.go index 876dbe01..2761e7cb 100644 --- a/config.go +++ b/config.go @@ -16,7 +16,6 @@ package beego import ( "fmt" - "html/template" "os" "path/filepath" "strings" @@ -106,8 +105,6 @@ var ( AppConfig *beegoAppConfig // AppPath is the absolute path to the app AppPath string - // TemplateCache stores template caching - TemplateCache map[string]*template.Template // GlobalSessions is the instance for the session manager GlobalSessions *session.Manager From f5adec31c65f562f8d79871d724bf7a9163173dc Mon Sep 17 00:00:00 2001 From: JessonChan Date: Fri, 4 Mar 2016 14:49:16 +0800 Subject: [PATCH 21/21] improve the template reader function --- controller.go | 68 ++++++++++++++------------------------------------- template.go | 14 ++++++++--- 2 files changed, 30 insertions(+), 52 deletions(-) diff --git a/controller.go b/controller.go index 54da81ec..372d8c0f 100644 --- a/controller.go +++ b/controller.go @@ -197,35 +197,9 @@ func (c *Controller) RenderString() (string, error) { // RenderBytes returns the bytes of rendered template string. Do not send out response. func (c *Controller) RenderBytes() ([]byte, error) { - //if the controller has set layout, then first get the tplname's content set the content to the layout - var buf bytes.Buffer - var err error - if c.Layout != "" { - if c.TplName == "" { - c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt - } - - if BConfig.RunMode == DEV { - buildFiles := []string{c.TplName} - if c.LayoutSections != nil { - for _, sectionTpl := range c.LayoutSections { - if sectionTpl == "" { - continue - } - buildFiles = append(buildFiles, sectionTpl) - } - } - BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...) - } - if t := getTemplateByName(c.TplName); t == nil { - panic("can't find templatefile in the path:" + c.TplName) - } else { - err = t.ExecuteTemplate(&buf, c.TplName, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err - } - } + buf, err := c.renderTemplate() + //if the controller has set layout, then first get the tplName's content set the content to the layout + if err == nil && c.Layout != "" { c.Data["LayoutContent"] = template.HTML(buf.String()) if c.LayoutSections != nil { @@ -234,11 +208,9 @@ func (c *Controller) RenderBytes() ([]byte, error) { c.Data[sectionName] = "" continue } - buf.Reset() - err = getTemplateByName(sectionTpl).ExecuteTemplate(&buf, sectionTpl, c.Data) + err = executeTemplate(&buf, sectionTpl, c.Data) if err != nil { - Trace("template Execute err:", err) return nil, err } c.Data[sectionName] = template.HTML(buf.String()) @@ -246,31 +218,29 @@ func (c *Controller) RenderBytes() ([]byte, error) { } buf.Reset() - err = getTemplateByName(c.Layout).ExecuteTemplate(&buf, c.Layout, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err - } - return buf.Bytes(), nil + executeTemplate(&buf, c.Layout, c.Data) } + return buf.Bytes(), err +} +func (c *Controller) renderTemplate() (bytes.Buffer, error) { + var buf bytes.Buffer if c.TplName == "" { c.TplName = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt } if BConfig.RunMode == DEV { - BuildTemplate(BConfig.WebConfig.ViewsPath, c.TplName) - } - if t := getTemplateByName(c.TplName); t == nil { - panic("can't find templatefile in the path:" + c.TplName) - } else { - buf.Reset() - err = t.ExecuteTemplate(&buf, c.TplName, c.Data) - if err != nil { - Trace("template Execute err:", err) - return nil, err + buildFiles := []string{c.TplName} + if c.Layout != "" && c.LayoutSections != nil { + for _, sectionTpl := range c.LayoutSections { + if sectionTpl == "" { + continue + } + buildFiles = append(buildFiles, sectionTpl) + } } + BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...) } - return buf.Bytes(), nil + return buf, executeTemplate(&buf, c.TplName, c.Data) } // Redirect sends the redirection response to url with status code. diff --git a/template.go b/template.go index da79d383..e6c43f87 100644 --- a/template.go +++ b/template.go @@ -18,6 +18,7 @@ import ( "errors" "fmt" "html/template" + "io" "io/ioutil" "os" "path/filepath" @@ -37,12 +38,19 @@ var ( beeTemplateExt = []string{"tpl", "html"} ) -func getTemplateByName(name string) *template.Template { - if BConfig.RunMode == "dev" { +func executeTemplate(wr io.Writer, name string, data interface{}) error { + if BConfig.RunMode == DEV { templatesLock.RLock() defer templatesLock.RUnlock() } - return beeTemplates[name] + if t, ok := beeTemplates[name]; ok { + err := t.ExecuteTemplate(wr, name, data) + if err != nil { + Trace("template Execute err:", err) + } + return err + } + panic("can't find templatefile in the path:" + name) } func init() {