From d1bba02958805ac40dd3b8c0d7f7a1ab744cf1b4 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 9 Dec 2015 23:35:04 +0800 Subject: [PATCH] refact beego config --- admin.go | 49 +-- app.go | 50 +-- beego.go | 38 +- config.go | 762 ++++++++++++++++------------------- config_test.go | 4 +- controller.go | 18 +- controller_test.go | 18 +- docs.go | 2 +- error.go | 4 +- filter_test.go | 6 + flash.go | 10 +- hooks.go | 28 +- parser.go | 12 +- plugins/cors/cors_test.go | 4 +- plugins/jwt/jwt.go | 140 ------- plugins/jwt/jwt_test.go | 88 ---- plugins/jwt/test/jwt.rsa | 15 - plugins/jwt/test/jwt.rsa.pub | 6 - router.go | 36 +- staticfile.go | 14 +- template.go | 12 +- 21 files changed, 485 insertions(+), 831 deletions(-) delete mode 100644 plugins/jwt/jwt.go delete mode 100644 plugins/jwt/jwt_test.go delete mode 100644 plugins/jwt/test/jwt.rsa delete mode 100644 plugins/jwt/test/jwt.rsa.pub diff --git a/admin.go b/admin.go index ddc936ef..a1f48fa0 100644 --- a/admin.go +++ b/admin.go @@ -85,50 +85,11 @@ func listConf(rw http.ResponseWriter, r *http.Request) { data := make(map[interface{}]interface{}) switch command { case "conf": - m := make(map[string]interface{}) - - m["AppName"] = AppName - m["AppPath"] = AppPath - m["AppConfigPath"] = AppConfigPath - m["StaticDir"] = StaticDir - m["StaticExtensionsToGzip"] = StaticExtensionsToGzip - m["HTTPAddr"] = HTTPAddr - m["HTTPPort"] = HTTPPort - m["HTTPTLS"] = EnableHTTPTLS - m["HTTPCertFile"] = HTTPCertFile - m["HTTPKeyFile"] = HTTPKeyFile - m["RecoverPanic"] = RecoverPanic - m["AutoRender"] = AutoRender - m["ViewsPath"] = ViewsPath - m["RunMode"] = RunMode - m["SessionOn"] = SessionOn - m["SessionProvider"] = SessionProvider - m["SessionName"] = SessionName - m["SessionGCMaxLifetime"] = SessionGCMaxLifetime - m["SessionProviderConfig"] = SessionProviderConfig - m["SessionCookieLifeTime"] = SessionCookieLifeTime - m["EnableFcgi"] = EnableFcgi - m["MaxMemory"] = MaxMemory - m["EnableGzip"] = EnableGzip - m["DirectoryIndex"] = DirectoryIndex - m["HTTPServerTimeOut"] = HTTPServerTimeOut - m["EnableErrorsShow"] = EnableErrorsShow - m["XSRFKEY"] = XSRFKEY - m["EnableXSRF"] = EnableXSRF - m["XSRFExpire"] = XSRFExpire - m["CopyRequestBody"] = CopyRequestBody - m["TemplateLeft"] = TemplateLeft - m["TemplateRight"] = TemplateRight - m["BeegoServerName"] = BeegoServerName - m["EnableAdmin"] = EnableAdmin - m["AdminHTTPAddr"] = AdminHTTPAddr - m["AdminHTTPPort"] = AdminHTTPPort - tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl)) tmpl = template.Must(tmpl.Parse(configTpl)) tmpl = template.Must(tmpl.Parse(defaultScriptsTpl)) - data["Content"] = m + data["Content"] = BConfig tmpl.Execute(rw, data) @@ -391,10 +352,10 @@ func (admin *adminApp) Run() { if len(toolbox.AdminTaskList) > 0 { toolbox.StartTask() } - addr := AdminHTTPAddr + addr := BConfig.Listen.AdminAddr - if AdminHTTPPort != 0 { - addr = fmt.Sprintf("%s:%d", AdminHTTPAddr, AdminHTTPPort) + if BConfig.Listen.AdminPort != 0 { + addr = fmt.Sprintf("%s:%d", BConfig.Listen.AdminAddr, BConfig.Listen.AdminPort) } for p, f := range admin.routers { http.Handle(p, f) @@ -402,7 +363,7 @@ func (admin *adminApp) Run() { BeeLogger.Info("Admin server Running on %s", addr) var err error - if Graceful { + if BConfig.Listen.Graceful { err = grace.ListenAndServe(addr, nil) } else { err = http.ListenAndServe(addr, nil) diff --git a/app.go b/app.go index ed57b978..e8d1bc47 100644 --- a/app.go +++ b/app.go @@ -52,10 +52,10 @@ func NewApp() *App { // Run beego application. func (app *App) Run() { - addr := HTTPAddr + addr := BConfig.Listen.HTTPAddr - if HTTPPort != 0 { - addr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPPort) + if BConfig.Listen.HTTPPort != 0 { + addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPAddr, BConfig.Listen.HTTPPort) } var ( @@ -64,8 +64,8 @@ func (app *App) Run() { ) endRunning := make(chan bool, 1) - if EnableFcgi { - if EnableStdIo { + if BConfig.Listen.EnableFcgi { + if BConfig.Listen.EnableStdIo { err = fcgi.Serve(nil, app.Handlers) // standard I/O if err == nil { BeeLogger.Info("Use FCGI via standard I/O") @@ -73,7 +73,7 @@ func (app *App) Run() { BeeLogger.Info("Cannot use FCGI via standard I/O", err) } } else { - if HTTPPort == 0 { + if BConfig.Listen.HTTPPort == 0 { // remove the Socket file before start if utils.FileExists(addr) { os.Remove(addr) @@ -88,23 +88,23 @@ func (app *App) Run() { err = fcgi.Serve(l, app.Handlers) } } else { - if Graceful { - httpsAddr := addr - app.Server.Addr = addr + if BConfig.Listen.Graceful { + httpsAddr := BConfig.Listen.HTTPSAddr + app.Server.Addr = httpsAddr app.Server.Handler = app.Handlers - app.Server.ReadTimeout = time.Duration(HTTPServerTimeOut) * time.Second - app.Server.WriteTimeout = time.Duration(HTTPServerTimeOut) * time.Second - if EnableHTTPTLS { + app.Server.ReadTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second + app.Server.WriteTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second + if BConfig.Listen.HTTPSEnable { go func() { time.Sleep(20 * time.Microsecond) - if HTTPSPort != 0 { - httpsAddr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPSPort) + if BConfig.Listen.HTTPSPort != 0 { + httpsAddr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort) app.Server.Addr = httpsAddr } server := grace.NewServer(httpsAddr, app.Handlers) server.Server.ReadTimeout = app.Server.ReadTimeout server.Server.WriteTimeout = app.Server.WriteTimeout - err := server.ListenAndServeTLS(HTTPCertFile, HTTPKeyFile) + err := server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile) if err != nil { BeeLogger.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid())) time.Sleep(100 * time.Microsecond) @@ -112,12 +112,12 @@ func (app *App) Run() { } }() } - if EnableHTTPListen { + if BConfig.Listen.HTTPEnable { go func() { server := grace.NewServer(addr, app.Handlers) server.Server.ReadTimeout = app.Server.ReadTimeout server.Server.WriteTimeout = app.Server.WriteTimeout - if ListenTCP4 { + if BConfig.Listen.ListenTCP4 { server.Network = "tcp4" } err := server.ListenAndServe() @@ -131,17 +131,17 @@ func (app *App) Run() { } else { app.Server.Addr = addr app.Server.Handler = app.Handlers - app.Server.ReadTimeout = time.Duration(HTTPServerTimeOut) * time.Second - app.Server.WriteTimeout = time.Duration(HTTPServerTimeOut) * time.Second + app.Server.ReadTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second + app.Server.WriteTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second - if EnableHTTPTLS { + if BConfig.Listen.HTTPSEnable { go func() { time.Sleep(20 * time.Microsecond) - if HTTPSPort != 0 { - app.Server.Addr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPSPort) + if BConfig.Listen.HTTPSPort != 0 { + app.Server.Addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort) } BeeLogger.Info("https server Running on %s", app.Server.Addr) - err := app.Server.ListenAndServeTLS(HTTPCertFile, HTTPKeyFile) + err := app.Server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile) if err != nil { BeeLogger.Critical("ListenAndServeTLS: ", err) time.Sleep(100 * time.Microsecond) @@ -150,11 +150,11 @@ func (app *App) Run() { }() } - if EnableHTTPListen { + if BConfig.Listen.HTTPEnable { go func() { app.Server.Addr = addr BeeLogger.Info("http server Running on %s", app.Server.Addr) - if ListenTCP4 { + if BConfig.Listen.ListenTCP4 { ln, err := net.Listen("tcp4", app.Server.Addr) if err != nil { BeeLogger.Critical("ListenAndServe: ", err) diff --git a/beego.go b/beego.go index 6c964d5a..a4d996e3 100644 --- a/beego.go +++ b/beego.go @@ -15,10 +15,13 @@ package beego import ( + "fmt" "os" "path/filepath" "strconv" "strings" + + "github.com/astaxie/beego/logs" ) // beego web framework version. @@ -49,10 +52,10 @@ func Run(params ...string) { if len(params) > 0 && params[0] != "" { strs := strings.Split(params[0], ":") if len(strs) > 0 && strs[0] != "" { - HTTPAddr = strs[0] + BConfig.Listen.HTTPAddr = strs[0] } if len(strs) > 1 && strs[1] != "" { - HTTPPort, _ = strconv.Atoi(strs[1]) + BConfig.Listen.HTTPPort, _ = strconv.Atoi(strs[1]) } } @@ -60,15 +63,22 @@ func Run(params ...string) { } func initBeforeHTTPRun() { - // if AppConfigPath not In the conf/app.conf reParse config - if AppConfigPath != filepath.Join(AppPath, "conf", "app.conf") { - err := ParseConfig() - if err != nil && AppConfigPath != filepath.Join(workPath, "conf", "app.conf") { - // configuration is critical to app, panic here if parse failed - panic(err) + // if AppConfigPath is setted or conf/app.conf exist + err := ParseConfig() + if err != nil { + panic(err) + } + //init log + BeeLogger = logs.NewLogger(10000) + for adaptor, config := range BConfig.Log.Output { + 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) AddAPPStartHook(registerDefaultErrorHandler) @@ -85,15 +95,9 @@ func initBeforeHTTPRun() { } // TestBeegoInit is for test package init -func TestBeegoInit(apppath string) { - AppPath = apppath +func TestBeegoInit(ap string) { os.Setenv("BEEGO_RUNMODE", "test") - AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") - err := ParseConfig() - if err != nil && !os.IsNotExist(err) { - // for init if doesn't have app.conf will not panic - Info(err) - } - os.Chdir(AppPath) + AppConfigPath = filepath.Join(ap, "conf", "app.conf") + os.Chdir(ap) initBeforeHTTPRun() } diff --git a/config.go b/config.go index 85da1c30..85b3eede 100644 --- a/config.go +++ b/config.go @@ -15,131 +15,372 @@ package beego import ( - "fmt" "html/template" "os" "path/filepath" - "runtime" "strings" "github.com/astaxie/beego/config" - "github.com/astaxie/beego/logs" "github.com/astaxie/beego/session" "github.com/astaxie/beego/utils" ) +type BeegoConfig struct { + AppName string //Application name + RunMode string //Running Mode: dev | prod + RouterCaseSensitive bool + ServerName string + RecoverPanic bool + CopyRequestBody bool + EnableGzip bool + MaxMemory int64 + EnableErrorsShow bool + Listen Listen + WebConfig WebConfig + Log LogConfig +} + +type Listen struct { + Graceful bool // Graceful means use graceful module to start the server + ServerTimeOut int64 + ListenTCP4 bool + HTTPEnable bool + HTTPAddr string + HTTPPort int + HTTPSEnable bool + HTTPSAddr string + HTTPSPort int + HTTPSCertFile string + HTTPSKeyFile string + AdminEnable bool + AdminAddr string + AdminPort int + EnableFcgi bool + EnableStdIo bool // EnableStdIo works with EnableFcgi Use FCGI via standard I/O +} + +type WebConfig struct { + AutoRender bool + EnableDocs bool + FlashName string + FlashSeperator string + DirectoryIndex bool + StaticDir map[string]string + StaticExtensionsToGzip []string + TemplateLeft string + TemplateRight string + ViewsPath string + EnableXSRF bool + XSRFKEY string + XSRFExpire int + Session SessionConfig +} + +type SessionConfig struct { + SessionOn bool + SessionProvider string + SessionName string + SessionGCMaxLifetime int64 + SessionProviderConfig string + SessionCookieLifeTime int + SessionAutoSetCookie bool + SessionDomain string +} + +type LogConfig struct { + AccessLogs bool + FileLineNum bool + Output map[string]string // Store Adaptor : config +} + var ( - // AccessLogs represent whether output the access logs, default is false - AccessLogs bool - // AdminHTTPAddr is address for admin - AdminHTTPAddr string - // AdminHTTPPort is listens port for admin - AdminHTTPPort int + // BConfig is the default config for Application + BConfig *BeegoConfig // AppConfig is the instance of Config, store the config information from file AppConfig *beegoAppConfig - // AppName represent Application name, always the project folder name - AppName string - // AppPath is the path to the application - AppPath string // AppConfigPath is the path to the config files AppConfigPath string // AppConfigProvider is the provider for the config, default is ini - AppConfigProvider string - // AutoRender is a flag of render template automatically. It's always turn off in API application - // default is true - AutoRender bool - // BeegoServerName exported in response header. - BeegoServerName string - // CopyRequestBody is just useful for raw request body in context. default is false - CopyRequestBody bool - // DirectoryIndex wheather display directory index. default is false. - DirectoryIndex bool - // EnableAdmin means turn on admin module to log every request info. - EnableAdmin bool - // EnableDocs enable generate docs & server docs API Swagger - EnableDocs bool - // EnableErrorsShow wheather show errors in page. if true, show error and trace info in page rendered with error template. - EnableErrorsShow bool - // EnableFcgi turn on the fcgi Listen, default is false - EnableFcgi bool - // EnableGzip means gzip the response - EnableGzip bool - // EnableHTTPListen represent whether turn on the HTTP, default is true - EnableHTTPListen bool - // EnableHTTPTLS represent whether turn on the HTTPS, default is true - EnableHTTPTLS bool - // EnableStdIo works with EnableFcgi Use FCGI via standard I/O - EnableStdIo bool - // EnableXSRF whether turn on xsrf. default is false - EnableXSRF bool - // FlashName is the name of the flash variable found in response header and cookie - FlashName string - // FlashSeperator used to seperate flash key:value, default is BEEGOFLASH - FlashSeperator string + AppConfigProvider = "ini" + // TemplateCache stores template caching + TemplateCache map[string]*template.Template // GlobalSessions is the instance for the session manager GlobalSessions *session.Manager - // Graceful means use graceful module to start the server - Graceful bool - // workPath is always the same as AppPath, but sometime when it started with other - // program, like supervisor - workPath string - // ListenTCP4 represent only Listen in TCP4, default is false - ListenTCP4 bool - // MaxMemory The whole request body is parsed and up to a total of maxMemory - // bytes of its file parts are stored in memory, with the remainder stored on disk in temporary files - MaxMemory int64 - // HTTPAddr is the TCP network address addr for HTTP - HTTPAddr string - // HTTPPort is listens port for HTTP - HTTPPort int - // HTTPSPort is listens port for HTTPS - HTTPSPort int - // HTTPCertFile is the path to certificate file - HTTPCertFile string - // HTTPKeyFile is the path to private key file - HTTPKeyFile string - // HTTPServerTimeOut HTTP server timeout. default is 0, no timeout - HTTPServerTimeOut int64 - // RecoverPanic is a flag for auto recover panic, default is true - RecoverPanic bool - // RouterCaseSensitive means whether router case sensitive, default is true - RouterCaseSensitive bool - // RunMode represent the staging, "dev" or "prod" - RunMode string - // SessionOn means whether turn on the session auto when application started. default is false. - SessionOn bool - // SessionProvider means session provider, e.q memory, mysql, redis,etc. - SessionProvider string - // SessionName is the cookie name when saving session id into cookie. - SessionName string - // SessionGCMaxLifetime for auto cleaning expired session. - SessionGCMaxLifetime int64 - // SessionProviderConfig is for the provider config, define save path or connection info. - SessionProviderConfig string - // SessionCookieLifeTime means the life time of session id in cookie. - SessionCookieLifeTime int - // SessionAutoSetCookie auto setcookie - SessionAutoSetCookie bool - // SessionDomain means the cookie domain default is empty - SessionDomain string - // StaticDir store the static path, key is path, value is the folder - StaticDir map[string]string - // StaticExtensionsToGzip stores the extensions which need to gzip(.js,.css,etc) - StaticExtensionsToGzip []string - // TemplateCache store the caching template - TemplateCache map[string]*template.Template - // TemplateLeft left delimiter - TemplateLeft string - // TemplateRight right delimiter - TemplateRight string - // ViewsPath means the template folder - ViewsPath string - // XSRFKEY xsrf hash salt string. - XSRFKEY string - // XSRFExpire is the expiry of xsrf value. - XSRFExpire int ) +func init() { + BConfig = &BeegoConfig{ + AppName: "beego", + RunMode: "dev", + RouterCaseSensitive: true, + ServerName: "beegoServer:" + VERSION, + RecoverPanic: true, + CopyRequestBody: false, + EnableGzip: false, + MaxMemory: 1 << 26, //64MB + EnableErrorsShow: true, + Listen: Listen{ + Graceful: false, + ServerTimeOut: 0, + ListenTCP4: false, + HTTPEnable: true, + HTTPAddr: "", + HTTPPort: 8080, + HTTPSEnable: false, + HTTPSAddr: "", + HTTPSPort: 10443, + HTTPSCertFile: "", + HTTPSKeyFile: "", + AdminEnable: false, + AdminAddr: "", + AdminPort: 8088, + EnableFcgi: false, + EnableStdIo: false, + }, + WebConfig: WebConfig{ + AutoRender: true, + EnableDocs: false, + FlashName: "BEEGO_FLASH", + FlashSeperator: "BEEGOFLASH", + DirectoryIndex: false, + StaticDir: map[string]string{"/static": "static"}, + StaticExtensionsToGzip: []string{".css", ".js"}, + TemplateLeft: "{{", + TemplateRight: "}}", + ViewsPath: "views", + EnableXSRF: false, + XSRFKEY: "beegoxsrf", + XSRFExpire: 0, + Session: SessionConfig{ + SessionOn: false, + SessionProvider: "memory", + SessionName: "beegosessionID", + SessionGCMaxLifetime: 3600, + SessionProviderConfig: "", + SessionCookieLifeTime: 0, //set cookie default is the brower life + SessionAutoSetCookie: true, + SessionDomain: "", + }, + }, + Log: LogConfig{ + AccessLogs: false, + FileLineNum: true, + Output: map[string]string{"console": ""}, + }, + } +} + +// ParseConfig parsed default config file. +// 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 { + ac := config.NewFakeConfig() + AppConfig = &beegoAppConfig{ac} + return + } + } + AppConfig, err = newAppConfig(AppConfigProvider, AppConfigPath) + if err != nil { + return err + } + envRunMode := os.Getenv("BEEGO_RUNMODE") + // set the runmode first + if envRunMode != "" { + BConfig.RunMode = envRunMode + } else if runmode := AppConfig.String("RunMode"); runmode != "" { + BConfig.RunMode = runmode + } + + BConfig.Listen.HTTPAddr = AppConfig.String("HTTPAddr") + + if v, err := AppConfig.Int("HTTPPort"); err == nil { + BConfig.Listen.HTTPPort = v + } + + if v, err := AppConfig.Bool("ListenTCP4"); err == nil { + BConfig.Listen.ListenTCP4 = v + } + + if v, err := AppConfig.Bool("EnableHTTPListen"); err == nil { + BConfig.Listen.HTTPEnable = v + } + + if maxmemory, err := AppConfig.Int64("MaxMemory"); err == nil { + BConfig.MaxMemory = maxmemory + } + + if appname := AppConfig.String("AppName"); appname != "" { + BConfig.AppName = appname + } + + if autorender, err := AppConfig.Bool("AutoRender"); err == nil { + BConfig.WebConfig.AutoRender = autorender + } + + if autorecover, err := AppConfig.Bool("RecoverPanic"); err == nil { + BConfig.RecoverPanic = autorecover + } + + if views := AppConfig.String("ViewsPath"); views != "" { + BConfig.WebConfig.ViewsPath = views + } + + if sessionon, err := AppConfig.Bool("SessionOn"); err == nil { + BConfig.WebConfig.Session.SessionOn = sessionon + } + + if sessProvider := AppConfig.String("SessionProvider"); sessProvider != "" { + BConfig.WebConfig.Session.SessionProvider = sessProvider + } + + if sessName := AppConfig.String("SessionName"); sessName != "" { + BConfig.WebConfig.Session.SessionName = sessName + } + + if sessProvConfig := AppConfig.String("SessionProviderConfig"); sessProvConfig != "" { + BConfig.WebConfig.Session.SessionProviderConfig = sessProvConfig + } + + if sessMaxLifeTime, err := AppConfig.Int64("SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 { + BConfig.WebConfig.Session.SessionGCMaxLifetime = sessMaxLifeTime + } + + if sesscookielifetime, err := AppConfig.Int("SessionCookieLifeTime"); err == nil && sesscookielifetime != 0 { + BConfig.WebConfig.Session.SessionCookieLifeTime = sesscookielifetime + } + + if enableFcgi, err := AppConfig.Bool("EnableFcgi"); err == nil { + BConfig.Listen.EnableFcgi = enableFcgi + } + + if enablegzip, err := AppConfig.Bool("EnableGzip"); err == nil { + BConfig.EnableGzip = enablegzip + } + + if directoryindex, err := AppConfig.Bool("DirectoryIndex"); err == nil { + BConfig.WebConfig.DirectoryIndex = directoryindex + } + + if timeout, err := AppConfig.Int64("HTTPServerTimeOut"); err == nil { + BConfig.Listen.ServerTimeOut = timeout + } + + if errorsshow, err := AppConfig.Bool("EnableErrorsShow"); err == nil { + BConfig.EnableErrorsShow = errorsshow + } + + if copyrequestbody, err := AppConfig.Bool("CopyRequestBody"); err == nil { + BConfig.CopyRequestBody = copyrequestbody + } + + if xsrfkey := AppConfig.String("XSRFKEY"); xsrfkey != "" { + BConfig.WebConfig.XSRFKEY = xsrfkey + } + + if enablexsrf, err := AppConfig.Bool("EnableXSRF"); err == nil { + BConfig.WebConfig.EnableXSRF = enablexsrf + } + + if expire, err := AppConfig.Int("XSRFExpire"); err == nil { + BConfig.WebConfig.XSRFExpire = expire + } + + if tplleft := AppConfig.String("TemplateLeft"); tplleft != "" { + BConfig.WebConfig.TemplateLeft = tplleft + } + + if tplright := AppConfig.String("TemplateRight"); tplright != "" { + BConfig.WebConfig.TemplateRight = tplright + } + + if httptls, err := AppConfig.Bool("EnableHTTPTLS"); err == nil { + BConfig.Listen.HTTPSEnable = httptls + } + + if httpsport, err := AppConfig.Int("HTTPSPort"); err == nil { + BConfig.Listen.HTTPSPort = httpsport + } + + if certfile := AppConfig.String("HTTPCertFile"); certfile != "" { + BConfig.Listen.HTTPSCertFile = certfile + } + + if keyfile := AppConfig.String("HTTPKeyFile"); keyfile != "" { + BConfig.Listen.HTTPSKeyFile = keyfile + } + + if serverName := AppConfig.String("BeegoServerName"); serverName != "" { + BConfig.ServerName = serverName + } + + if flashname := AppConfig.String("FlashName"); flashname != "" { + BConfig.WebConfig.FlashName = flashname + } + + if flashseperator := AppConfig.String("FlashSeperator"); flashseperator != "" { + BConfig.WebConfig.FlashSeperator = flashseperator + } + + if sd := AppConfig.String("StaticDir"); sd != "" { + for k := range BConfig.WebConfig.StaticDir { + delete(BConfig.WebConfig.StaticDir, k) + } + sds := strings.Fields(sd) + for _, v := range sds { + if url2fsmap := strings.SplitN(v, ":", 2); len(url2fsmap) == 2 { + BConfig.WebConfig.StaticDir["/"+strings.TrimRight(url2fsmap[0], "/")] = url2fsmap[1] + } else { + BConfig.WebConfig.StaticDir["/"+strings.TrimRight(url2fsmap[0], "/")] = url2fsmap[0] + } + } + } + + if sgz := AppConfig.String("StaticExtensionsToGzip"); sgz != "" { + extensions := strings.Split(sgz, ",") + fileExts := []string{} + for _, ext := range extensions { + ext = strings.TrimSpace(ext) + if ext == "" { + continue + } + if !strings.HasPrefix(ext, ".") { + ext = "." + ext + } + fileExts = append(fileExts, ext) + } + if len(fileExts) > 0 { + BConfig.WebConfig.StaticExtensionsToGzip = fileExts + } + } + + if enableadmin, err := AppConfig.Bool("EnableAdmin"); err == nil { + BConfig.Listen.AdminEnable = enableadmin + } + + if adminhttpaddr := AppConfig.String("AdminHTTPAddr"); adminhttpaddr != "" { + BConfig.Listen.AdminAddr = adminhttpaddr + } + + if adminhttpport, err := AppConfig.Int("AdminHTTPPort"); err == nil { + BConfig.Listen.AdminPort = adminhttpport + } + + if enabledocs, err := AppConfig.Bool("EnableDocs"); err == nil { + BConfig.WebConfig.EnableDocs = enabledocs + } + + if casesensitive, err := AppConfig.Bool("RouterCaseSensitive"); err == nil { + BConfig.RouterCaseSensitive = casesensitive + } + if graceful, err := AppConfig.Bool("Graceful"); err == nil { + BConfig.Listen.Graceful = graceful + } + return nil +} + type beegoAppConfig struct { innerConfig config.Configer } @@ -154,7 +395,7 @@ func newAppConfig(AppConfigProvider, AppConfigPath string) (*beegoAppConfig, err } func (b *beegoAppConfig) Set(key, val string) error { - err := b.innerConfig.Set(RunMode+"::"+key, val) + err := b.innerConfig.Set(BConfig.RunMode+"::"+key, val) if err == nil { return err } @@ -162,7 +403,7 @@ func (b *beegoAppConfig) Set(key, val string) error { } func (b *beegoAppConfig) String(key string) string { - v := b.innerConfig.String(RunMode + "::" + key) + v := b.innerConfig.String(BConfig.RunMode + "::" + key) if v == "" { return b.innerConfig.String(key) } @@ -170,7 +411,7 @@ func (b *beegoAppConfig) String(key string) string { } func (b *beegoAppConfig) Strings(key string) []string { - v := b.innerConfig.Strings(RunMode + "::" + key) + v := b.innerConfig.Strings(BConfig.RunMode + "::" + key) if v[0] == "" { return b.innerConfig.Strings(key) } @@ -178,7 +419,7 @@ func (b *beegoAppConfig) Strings(key string) []string { } func (b *beegoAppConfig) Int(key string) (int, error) { - v, err := b.innerConfig.Int(RunMode + "::" + key) + v, err := b.innerConfig.Int(BConfig.RunMode + "::" + key) if err != nil { return b.innerConfig.Int(key) } @@ -186,7 +427,7 @@ func (b *beegoAppConfig) Int(key string) (int, error) { } func (b *beegoAppConfig) Int64(key string) (int64, error) { - v, err := b.innerConfig.Int64(RunMode + "::" + key) + v, err := b.innerConfig.Int64(BConfig.RunMode + "::" + key) if err != nil { return b.innerConfig.Int64(key) } @@ -194,7 +435,7 @@ func (b *beegoAppConfig) Int64(key string) (int64, error) { } func (b *beegoAppConfig) Bool(key string) (bool, error) { - v, err := b.innerConfig.Bool(RunMode + "::" + key) + v, err := b.innerConfig.Bool(BConfig.RunMode + "::" + key) if err != nil { return b.innerConfig.Bool(key) } @@ -202,7 +443,7 @@ func (b *beegoAppConfig) Bool(key string) (bool, error) { } func (b *beegoAppConfig) Float(key string) (float64, error) { - v, err := b.innerConfig.Float(RunMode + "::" + key) + v, err := b.innerConfig.Float(BConfig.RunMode + "::" + key) if err != nil { return b.innerConfig.Float(key) } @@ -268,300 +509,3 @@ func (b *beegoAppConfig) GetSection(section string) (map[string]string, error) { func (b *beegoAppConfig) SaveConfigFile(filename string) error { return b.innerConfig.SaveConfigFile(filename) } - -func init() { - workPath, _ = os.Getwd() - workPath, _ = filepath.Abs(workPath) - // initialize default configurations - AppPath, _ = filepath.Abs(filepath.Dir(os.Args[0])) - - AppConfigPath = filepath.Join(AppPath, "conf", "app.conf") - - if workPath != AppPath { - if utils.FileExists(AppConfigPath) { - os.Chdir(AppPath) - } else { - AppConfigPath = filepath.Join(workPath, "conf", "app.conf") - } - } - - AppConfigProvider = "ini" - - StaticDir = make(map[string]string) - StaticDir["/static"] = "static" - - StaticExtensionsToGzip = []string{".css", ".js"} - - TemplateCache = make(map[string]*template.Template) - - // set this to 0.0.0.0 to make this app available to externally - EnableHTTPListen = true //default enable http Listen - - HTTPAddr = "" - HTTPPort = 8080 - - HTTPSPort = 10443 - - AppName = "beego" - - RunMode = "dev" //default runmod - - AutoRender = true - - RecoverPanic = true - - ViewsPath = "views" - - SessionOn = false - SessionProvider = "memory" - SessionName = "beegosessionID" - SessionGCMaxLifetime = 3600 - SessionProviderConfig = "" - SessionCookieLifeTime = 0 //set cookie default is the brower life - SessionAutoSetCookie = true - - MaxMemory = 1 << 26 //64MB - - HTTPServerTimeOut = 0 - - EnableErrorsShow = true - - XSRFKEY = "beegoxsrf" - XSRFExpire = 0 - - TemplateLeft = "{{" - TemplateRight = "}}" - - BeegoServerName = "beegoServer:" + VERSION - - EnableAdmin = false - AdminHTTPAddr = "127.0.0.1" - AdminHTTPPort = 8088 - - FlashName = "BEEGO_FLASH" - FlashSeperator = "BEEGOFLASH" - - RouterCaseSensitive = true - - runtime.GOMAXPROCS(runtime.NumCPU()) - - // init BeeLogger - BeeLogger = logs.NewLogger(10000) - err := BeeLogger.SetLogger("console", "") - if err != nil { - fmt.Println("init console log error:", err) - } - SetLogFuncCall(true) - - err = ParseConfig() - if err != nil { - if os.IsNotExist(err) { - // for init if doesn't have app.conf will not panic - ac := config.NewFakeConfig() - AppConfig = &beegoAppConfig{ac} - } - Warning(err) - } -} - -// ParseConfig parsed default config file. -// now only support ini, next will support json. -func ParseConfig() (err error) { - AppConfig, err = newAppConfig(AppConfigProvider, AppConfigPath) - if err != nil { - return err - } - envRunMode := os.Getenv("BEEGO_RUNMODE") - // set the runmode first - if envRunMode != "" { - RunMode = envRunMode - } else if runmode := AppConfig.String("RunMode"); runmode != "" { - RunMode = runmode - } - - HTTPAddr = AppConfig.String("HTTPAddr") - - if v, err := AppConfig.Int("HTTPPort"); err == nil { - HTTPPort = v - } - - if v, err := AppConfig.Bool("ListenTCP4"); err == nil { - ListenTCP4 = v - } - - if v, err := AppConfig.Bool("EnableHTTPListen"); err == nil { - EnableHTTPListen = v - } - - if maxmemory, err := AppConfig.Int64("MaxMemory"); err == nil { - MaxMemory = maxmemory - } - - if appname := AppConfig.String("AppName"); appname != "" { - AppName = appname - } - - if autorender, err := AppConfig.Bool("AutoRender"); err == nil { - AutoRender = autorender - } - - if autorecover, err := AppConfig.Bool("RecoverPanic"); err == nil { - RecoverPanic = autorecover - } - - if views := AppConfig.String("ViewsPath"); views != "" { - ViewsPath = views - } - - if sessionon, err := AppConfig.Bool("SessionOn"); err == nil { - SessionOn = sessionon - } - - if sessProvider := AppConfig.String("SessionProvider"); sessProvider != "" { - SessionProvider = sessProvider - } - - if sessName := AppConfig.String("SessionName"); sessName != "" { - SessionName = sessName - } - - if sessProvConfig := AppConfig.String("SessionProviderConfig"); sessProvConfig != "" { - SessionProviderConfig = sessProvConfig - } - - if sessMaxLifeTime, err := AppConfig.Int64("SessionGCMaxLifetime"); err == nil && sessMaxLifeTime != 0 { - SessionGCMaxLifetime = sessMaxLifeTime - } - - if sesscookielifetime, err := AppConfig.Int("SessionCookieLifeTime"); err == nil && sesscookielifetime != 0 { - SessionCookieLifeTime = sesscookielifetime - } - - if enableFcgi, err := AppConfig.Bool("EnableFcgi"); err == nil { - EnableFcgi = enableFcgi - } - - if enablegzip, err := AppConfig.Bool("EnableGzip"); err == nil { - EnableGzip = enablegzip - } - - if directoryindex, err := AppConfig.Bool("DirectoryIndex"); err == nil { - DirectoryIndex = directoryindex - } - - if timeout, err := AppConfig.Int64("HTTPServerTimeOut"); err == nil { - HTTPServerTimeOut = timeout - } - - if errorsshow, err := AppConfig.Bool("EnableErrorsShow"); err == nil { - EnableErrorsShow = errorsshow - } - - if copyrequestbody, err := AppConfig.Bool("CopyRequestBody"); err == nil { - CopyRequestBody = copyrequestbody - } - - if xsrfkey := AppConfig.String("XSRFKEY"); xsrfkey != "" { - XSRFKEY = xsrfkey - } - - if enablexsrf, err := AppConfig.Bool("EnableXSRF"); err == nil { - EnableXSRF = enablexsrf - } - - if expire, err := AppConfig.Int("XSRFExpire"); err == nil { - XSRFExpire = expire - } - - if tplleft := AppConfig.String("TemplateLeft"); tplleft != "" { - TemplateLeft = tplleft - } - - if tplright := AppConfig.String("TemplateRight"); tplright != "" { - TemplateRight = tplright - } - - if httptls, err := AppConfig.Bool("EnableHTTPTLS"); err == nil { - EnableHTTPTLS = httptls - } - - if httpsport, err := AppConfig.Int("HTTPSPort"); err == nil { - HTTPSPort = httpsport - } - - if certfile := AppConfig.String("HTTPCertFile"); certfile != "" { - HTTPCertFile = certfile - } - - if keyfile := AppConfig.String("HTTPKeyFile"); keyfile != "" { - HTTPKeyFile = keyfile - } - - if serverName := AppConfig.String("BeegoServerName"); serverName != "" { - BeegoServerName = serverName - } - - if flashname := AppConfig.String("FlashName"); flashname != "" { - FlashName = flashname - } - - if flashseperator := AppConfig.String("FlashSeperator"); flashseperator != "" { - FlashSeperator = flashseperator - } - - if sd := AppConfig.String("StaticDir"); sd != "" { - for k := range StaticDir { - delete(StaticDir, k) - } - sds := strings.Fields(sd) - for _, v := range sds { - if url2fsmap := strings.SplitN(v, ":", 2); len(url2fsmap) == 2 { - StaticDir["/"+strings.TrimRight(url2fsmap[0], "/")] = url2fsmap[1] - } else { - StaticDir["/"+strings.TrimRight(url2fsmap[0], "/")] = url2fsmap[0] - } - } - } - - if sgz := AppConfig.String("StaticExtensionsToGzip"); sgz != "" { - extensions := strings.Split(sgz, ",") - fileExts := []string{} - for _, ext := range extensions { - ext = strings.TrimSpace(ext) - if ext == "" { - continue - } - if !strings.HasPrefix(ext, ".") { - ext = "." + ext - } - fileExts = append(fileExts, ext) - } - if len(fileExts) > 0 { - StaticExtensionsToGzip = fileExts - } - } - - if enableadmin, err := AppConfig.Bool("EnableAdmin"); err == nil { - EnableAdmin = enableadmin - } - - if adminhttpaddr := AppConfig.String("AdminHTTPAddr"); adminhttpaddr != "" { - AdminHTTPAddr = adminhttpaddr - } - - if adminhttpport, err := AppConfig.Int("AdminHTTPPort"); err == nil { - AdminHTTPPort = adminhttpport - } - - if enabledocs, err := AppConfig.Bool("EnableDocs"); err == nil { - EnableDocs = enabledocs - } - - if casesensitive, err := AppConfig.Bool("RouterCaseSensitive"); err == nil { - RouterCaseSensitive = casesensitive - } - if graceful, err := AppConfig.Bool("Graceful"); err == nil { - Graceful = graceful - } - return nil -} diff --git a/config_test.go b/config_test.go index 17645f80..a74471fc 100644 --- a/config_test.go +++ b/config_test.go @@ -19,11 +19,11 @@ import ( ) func TestDefaults(t *testing.T) { - if FlashName != "BEEGO_FLASH" { + if BConfig.WebConfig.FlashName != "BEEGO_FLASH" { t.Errorf("FlashName was not set to default.") } - if FlashSeperator != "BEEGOFLASH" { + if BConfig.WebConfig.FlashSeperator != "BEEGOFLASH" { t.Errorf("FlashName was not set to default.") } } diff --git a/controller.go b/controller.go index 0750daf4..2febb50d 100644 --- a/controller.go +++ b/controller.go @@ -200,7 +200,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt } - if RunMode == "dev" { + if BConfig.RunMode == "dev" { buildFiles := make([]string, 1) buildFiles = append(buildFiles, c.TplNames) if c.LayoutSections != nil { @@ -211,7 +211,7 @@ func (c *Controller) RenderBytes() ([]byte, error) { buildFiles = append(buildFiles, sectionTpl) } } - BuildTemplate(ViewsPath, buildFiles...) + BuildTemplate(BConfig.WebConfig.ViewsPath, buildFiles...) } newbytes := bytes.NewBufferString("") if _, ok := BeeTemplates[c.TplNames]; !ok { @@ -256,8 +256,8 @@ func (c *Controller) RenderBytes() ([]byte, error) { if c.TplNames == "" { c.TplNames = strings.ToLower(c.controllerName) + "/" + strings.ToLower(c.actionName) + "." + c.TplExt } - if RunMode == "dev" { - BuildTemplate(ViewsPath, c.TplNames) + if BConfig.RunMode == "dev" { + BuildTemplate(BConfig.WebConfig.ViewsPath, c.TplNames) } ibytes := bytes.NewBufferString("") if _, ok := BeeTemplates[c.TplNames]; !ok { @@ -319,7 +319,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { func (c *Controller) ServeJSON(encoding ...bool) { var hasIndent bool var hasencoding bool - if RunMode == "prod" { + if BConfig.RunMode == "prod" { hasIndent = false } else { hasIndent = true @@ -333,7 +333,7 @@ func (c *Controller) ServeJSON(encoding ...bool) { // ServeJSONP sends a jsonp response. func (c *Controller) ServeJSONP() { var hasIndent bool - if RunMode == "prod" { + if BConfig.RunMode == "prod" { hasIndent = false } else { hasIndent = true @@ -344,7 +344,7 @@ func (c *Controller) ServeJSONP() { // ServeXML sends xml response. func (c *Controller) ServeXML() { var hasIndent bool - if RunMode == "prod" { + if BConfig.RunMode == "prod" { hasIndent = false } else { hasIndent = true @@ -628,9 +628,9 @@ func (c *Controller) XSRFToken() string { if c.XSRFExpire > 0 { expire = int64(c.XSRFExpire) } else { - expire = int64(XSRFExpire) + expire = int64(BConfig.WebConfig.XSRFExpire) } - c._xsrfToken = c.Ctx.XSRFToken(XSRFKEY, expire) + c._xsrfToken = c.Ctx.XSRFToken(BConfig.WebConfig.XSRFKEY, expire) } return c._xsrfToken } diff --git a/controller_test.go b/controller_test.go index 4156bd29..ebf38b2c 100644 --- a/controller_test.go +++ b/controller_test.go @@ -15,30 +15,25 @@ package beego import ( - "fmt" - "github.com/astaxie/beego/context" "testing" + + "github.com/astaxie/beego/context" ) func TestGetInt(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} - val, _ := ctrlr.GetInt("age") - - if (val != 40) { + if val != 40 { t.Errorf("TestGetInt expect 40,get %T,%v", val, val) } } func TestGetInt8(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} - val, _ := ctrlr.GetInt8("age") if val != 40 { t.Errorf("TestGetInt8 expect 40,get %T,%v", val, val) @@ -47,11 +42,9 @@ func TestGetInt8(t *testing.T) { } func TestGetInt16(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} - val, _ := ctrlr.GetInt16("age") if val != 40 { t.Errorf("TestGetInt16 expect 40,get %T,%v", val, val) @@ -59,24 +52,19 @@ func TestGetInt16(t *testing.T) { } func TestGetInt32(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} - val, _ := ctrlr.GetInt32("age") - fmt.Printf("%T", val) if val != 40 { t.Errorf("TestGetInt32 expect 40,get %T,%v", val, val) } } func TestGetInt64(t *testing.T) { - i := &context.BeegoInput{Params: map[string]string{"age": "40"}} ctx := &context.Context{Input: i} ctrlr := Controller{Ctx: ctx} - val, _ := ctrlr.GetInt64("age") if val != 40 { t.Errorf("TestGeetInt64 expect 40,get %T,%v", val, val) diff --git a/docs.go b/docs.go index 1dbed6cc..5031dc12 100644 --- a/docs.go +++ b/docs.go @@ -24,7 +24,7 @@ import ( var GlobalDocAPI map[string]interface{} func init() { - if EnableDocs { + if BConfig.WebConfig.EnableDocs { GlobalDocAPI = make(map[string]interface{}) } } diff --git a/error.go b/error.go index 2a1a861d..0010c814 100644 --- a/error.go +++ b/error.go @@ -85,7 +85,7 @@ var tpl = ` func showErr(err interface{}, ctx *context.Context, Stack string) { t, _ := template.New("beegoerrortemp").Parse(tpl) data := make(map[string]string) - data["AppError"] = AppName + ":" + fmt.Sprint(err) + data["AppError"] = BConfig.AppName + ":" + fmt.Sprint(err) data["RequestMethod"] = ctx.Input.Method() data["RequestURL"] = ctx.Input.URI() data["RemoteAddr"] = ctx.Input.IP() @@ -437,7 +437,7 @@ func executeError(err *errorInfo, ctx *context.Context, code int) { method.Call(in) //render template - if AutoRender { + if BConfig.WebConfig.AutoRender { if err := execController.Render(); err != nil { panic(err) } diff --git a/filter_test.go b/filter_test.go index ff6f750b..b1cd9c94 100644 --- a/filter_test.go +++ b/filter_test.go @@ -20,8 +20,14 @@ import ( "testing" "github.com/astaxie/beego/context" + "github.com/astaxie/beego/logs" ) +func init() { + BeeLogger = logs.NewLogger(10000) + BeeLogger.SetLogger("console", "") +} + var FilterUser = func(ctx *context.Context) { ctx.Output.Body([]byte("i am " + ctx.Input.Params[":last"] + ctx.Input.Params[":first"])) } diff --git a/flash.go b/flash.go index 5ccf339a..123bfdc3 100644 --- a/flash.go +++ b/flash.go @@ -83,27 +83,27 @@ func (fd *FlashData) Store(c *Controller) { c.Data["flash"] = fd.Data var flashValue string for key, value := range fd.Data { - flashValue += "\x00" + key + "\x23" + FlashSeperator + "\x23" + value + "\x00" + flashValue += "\x00" + key + "\x23" + BConfig.WebConfig.FlashSeperator + "\x23" + value + "\x00" } - c.Ctx.SetCookie(FlashName, url.QueryEscape(flashValue), 0, "/") + c.Ctx.SetCookie(BConfig.WebConfig.FlashName, url.QueryEscape(flashValue), 0, "/") } // ReadFromRequest parsed flash data from encoded values in cookie. func ReadFromRequest(c *Controller) *FlashData { flash := NewFlash() - if cookie, err := c.Ctx.Request.Cookie(FlashName); err == nil { + if cookie, err := c.Ctx.Request.Cookie(BConfig.WebConfig.FlashName); err == nil { v, _ := url.QueryUnescape(cookie.Value) vals := strings.Split(v, "\x00") for _, v := range vals { if len(v) > 0 { - kv := strings.Split(v, "\x23"+FlashSeperator+"\x23") + kv := strings.Split(v, "\x23"+BConfig.WebConfig.FlashSeperator+"\x23") if len(kv) == 2 { flash.Data[kv[0]] = kv[1] } } } //read one time then delete it - c.Ctx.SetCookie(FlashName, "", -1, "/") + c.Ctx.SetCookie(BConfig.WebConfig.FlashName, "", -1, "/") } c.Data["flash"] = flash.Data return flash diff --git a/hooks.go b/hooks.go index 6e401c06..61b80ad3 100644 --- a/hooks.go +++ b/hooks.go @@ -41,19 +41,19 @@ func registerDefaultErrorHandler() error { } func registerSession() error { - if SessionOn { + if BConfig.WebConfig.Session.SessionOn { var err error sessionConfig := AppConfig.String("sessionConfig") if sessionConfig == "" { - sessionConfig = `{"cookieName":"` + SessionName + `",` + - `"gclifetime":` + strconv.FormatInt(SessionGCMaxLifetime, 10) + `,` + - `"providerConfig":"` + filepath.ToSlash(SessionProviderConfig) + `",` + - `"secure":` + strconv.FormatBool(EnableHTTPTLS) + `,` + - `"enableSetCookie":` + strconv.FormatBool(SessionAutoSetCookie) + `,` + - `"domain":"` + SessionDomain + `",` + - `"cookieLifeTime":` + strconv.Itoa(SessionCookieLifeTime) + `}` + sessionConfig = `{"cookieName":"` + BConfig.WebConfig.Session.SessionName + `",` + + `"gclifetime":` + strconv.FormatInt(BConfig.WebConfig.Session.SessionGCMaxLifetime, 10) + `,` + + `"providerConfig":"` + filepath.ToSlash(BConfig.WebConfig.Session.SessionProviderConfig) + `",` + + `"secure":` + strconv.FormatBool(BConfig.Listen.HTTPSEnable) + `,` + + `"enableSetCookie":` + strconv.FormatBool(BConfig.WebConfig.Session.SessionAutoSetCookie) + `,` + + `"domain":"` + BConfig.WebConfig.Session.SessionDomain + `",` + + `"cookieLifeTime":` + strconv.Itoa(BConfig.WebConfig.Session.SessionCookieLifeTime) + `}` } - GlobalSessions, err = session.NewManager(SessionProvider, sessionConfig) + GlobalSessions, err = session.NewManager(BConfig.WebConfig.Session.SessionProvider, sessionConfig) if err != nil { return err } @@ -63,9 +63,9 @@ func registerSession() error { } func registerTemplate() error { - if AutoRender { - err := BuildTemplate(ViewsPath) - if err != nil && RunMode == "dev" { + if BConfig.WebConfig.AutoRender { + err := BuildTemplate(BConfig.WebConfig.ViewsPath) + if err != nil && BConfig.RunMode == "dev" { Warn(err) } } @@ -73,7 +73,7 @@ func registerTemplate() error { } func registerDocs() error { - if EnableDocs { + if BConfig.WebConfig.EnableDocs { Get("/docs", serverDocs) Get("/docs/*", serverDocs) } @@ -81,7 +81,7 @@ func registerDocs() error { } func registerAdmin() error { - if EnableAdmin { + if BConfig.Listen.AdminEnable { go beeAdminApp.Run() } return nil diff --git a/parser.go b/parser.go index 7e8670cb..b14d74b9 100644 --- a/parser.go +++ b/parser.go @@ -130,7 +130,7 @@ func parserComments(comments *ast.CommentGroup, funcName, controllerName, pkgpat } func genRouterCode() { - os.Mkdir(path.Join(workPath, "routers"), 0755) + os.Mkdir("routers", 0755) Info("generate router from comments") var ( globalinfo string @@ -172,7 +172,7 @@ func genRouterCode() { } } if globalinfo != "" { - f, err := os.Create(path.Join(workPath, "routers", commentFilename)) + f, err := os.Create(path.Join("routers", commentFilename)) if err != nil { panic(err) } @@ -182,11 +182,11 @@ func genRouterCode() { } func compareFile(pkgRealpath string) bool { - if !utils.FileExists(path.Join(workPath, "routers", commentFilename)) { + if !utils.FileExists(path.Join("routers", commentFilename)) { return true } - if utils.FileExists(path.Join(workPath, lastupdateFilename)) { - content, err := ioutil.ReadFile(path.Join(workPath, lastupdateFilename)) + if utils.FileExists(lastupdateFilename) { + content, err := ioutil.ReadFile(lastupdateFilename) if err != nil { return true } @@ -214,7 +214,7 @@ func savetoFile(pkgRealpath string) { if err != nil { return } - ioutil.WriteFile(path.Join(workPath, lastupdateFilename), d, os.ModePerm) + ioutil.WriteFile(lastupdateFilename, d, os.ModePerm) } func getpathTime(pkgRealpath string) (lastupdate int64, err error) { diff --git a/plugins/cors/cors_test.go b/plugins/cors/cors_test.go index 56816dd9..ee5ee238 100644 --- a/plugins/cors/cors_test.go +++ b/plugins/cors/cors_test.go @@ -220,7 +220,7 @@ func Test_Preflight(t *testing.T) { func Benchmark_WithoutCORS(b *testing.B) { recorder := httptest.NewRecorder() handler := beego.NewControllerRegister() - beego.RunMode = "prod" + beego.BConfig.RunMode = "prod" handler.Any("/foo", func(ctx *context.Context) { ctx.Output.SetStatus(500) }) @@ -234,7 +234,7 @@ func Benchmark_WithoutCORS(b *testing.B) { func Benchmark_WithCORS(b *testing.B) { recorder := httptest.NewRecorder() handler := beego.NewControllerRegister() - beego.RunMode = "prod" + beego.BConfig.RunMode = "prod" handler.InsertFilter("*", beego.BeforeRouter, Allow(&Options{ AllowAllOrigins: true, AllowCredentials: true, diff --git a/plugins/jwt/jwt.go b/plugins/jwt/jwt.go deleted file mode 100644 index 49bc0e3b..00000000 --- a/plugins/jwt/jwt.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2014 beego Author. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package jwt provides JWT (Json Web Token) authentication -// -// Usage -// In file main.go -// -// import ( -// "github.com/astaxie/beego" -// "github.com/astaxie/beego/plugins/jwt" -// ) -// -// func main() { -// // JWT for Url matching /v1/* -// // PrivateKeyPath: The path for the private RSA key used by JWT -// // PublicKeyPath: The path for the public RSA key used by JWT -// // The list of Urls should be excluded from the JWT Auth -// beego.InsertFilter("/v1/*", beego.BeforeRouter, jwt.AuthRequest(&jwt.Options{ -// PrivateKeyPath: "conf/beeblog.rsa", -// PublicKeyPath: "conf/beeblog.rsa.pub", -// WhiteList: []string{"/v1/jwt/issue-token", "/docs"}, -// })) -// beego.Run() -// } -// -// In file routers/router.go -// -// import ( -// "github.com/astaxie/beego" -// "github.com/astaxie/beego/plugins/jwt" -// ) -// func init() { -// ns := beego.NSNamespace("/jwt", -// beego.NSInclude( -// &jwt.JwtController{}, -// ), -// ) -// beego.AddNamespace(ns) -// } -// -package jwt - -import ( - "io/ioutil" - "net/http" - "time" - - "github.com/astaxie/beego" - "github.com/astaxie/beego/context" - "github.com/astaxie/beego/logs" - goJwt "github.com/dgrijalva/jwt-go" -) - -// Options for the JWT Auth -type Options struct { - PrivateKeyPath string - PublicKeyPath string - WhiteList []string -} - -// RSAKeys store PrivateKey and PublicKey -var RSAKeys struct { - PrivateKey []byte - PublicKey []byte -} - -// AuthRequest retunn FilterFunc -func AuthRequest(o *Options) beego.FilterFunc { - RSAKeys.PrivateKey, _ = ioutil.ReadFile(o.PrivateKeyPath) - RSAKeys.PublicKey, _ = ioutil.ReadFile(o.PublicKeyPath) - - return func(ctx *context.Context) { - // :TODO the url patterns should be considered here. - // Shouldn't only use the string equal - for _, method := range o.WhiteList { - if method == ctx.Request.URL.Path { - return - } - } - - parsedToken, err := goJwt.ParseFromRequest(ctx.Request, func(t *goJwt.Token) (interface{}, error) { - return RSAKeys.PublicKey, nil - }) - - if err == nil && parsedToken.Valid { - ctx.Output.SetStatus(http.StatusOK) - } else { - ctx.Output.SetStatus(http.StatusUnauthorized) - } - - } -} - -// Controller oprations for Jwt -type Controller struct { - beego.Controller -} - -// URLMapping is used to mapping the string to method -func (c *Controller) URLMapping() { - c.Mapping("IssueToken", c.IssueToken) -} - -// IssueToken function -// @Title IssueToken -// @Description Issue a Json Web Token -// @Success 200 string -// @Failure 403 no privilege to access -// @Failure 500 server inner error -// @router /issue-token [get] -func (c *Controller) IssueToken() { - c.Data["json"] = CreateToken() - c.ServeJSON() -} - -// CreateToken return the token -func CreateToken() map[string]string { - log := logs.NewLogger(10000) - log.SetLogger("console", "") - - token := goJwt.New(goJwt.GetSigningMethod("RS256")) // Create a Token that will be signed with RSA 256. - token.Claims["ID"] = "This is my super fake ID" - token.Claims["exp"] = time.Now().Unix() + 36000 - // The claims object allows you to store information in the actual token. - tokenString, _ := token.SignedString(RSAKeys.PrivateKey) - // tokenString Contains the actual token you should share with your client. - return map[string]string{"token": tokenString} -} diff --git a/plugins/jwt/jwt_test.go b/plugins/jwt/jwt_test.go deleted file mode 100644 index dd8cafe7..00000000 --- a/plugins/jwt/jwt_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package jwt - -import ( - "github.com/astaxie/beego" - "net/http" - "net/http/httptest" - "testing" -) - -func testRequest(method, path string) (*httptest.ResponseRecorder, *http.Request) { - request, _ := http.NewRequest(method, path, nil) - recorder := httptest.NewRecorder() - - return recorder, request -} - -func Test_IssueTokenAction(t *testing.T) { - url := "/v1/jwt/issue-token" - - mux := beego.NewControllerRegister() - - mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{ - PrivateKeyPath: "test/jwt.rsa", - PublicKeyPath: "test/jwt.rsa.pub", - WhiteList: []string{"/v1/jwt/issue-token", "/docs"}, - })) - - mux.Add("/v1/jwt/issue-token", &JwtController{}, "get:IssueToken") - - rw, r := testRequest("GET", url) - mux.ServeHTTP(rw, r) - - if rw.Code != http.StatusOK { - t.Errorf("Shoud return 200") - } -} - -func (tc *JwtController) Foo() { - tc.Ctx.Output.Body([]byte("ok")) -} - -func Test_AuthRequestWithAuthorizationHeader(t *testing.T) { - - url := "/foo" - - mux := beego.NewControllerRegister() - - mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{ - PrivateKeyPath: "test/jwt.rsa", - PublicKeyPath: "test/jwt.rsa.pub", - WhiteList: []string{"/v1/jwt/issue-token", "/docs"}, - })) - - mux.Add("/foo", &JwtController{}, "get:Foo") - newToken := CreateToken() - - rw, r := testRequest("GET", url) - r.Header.Add("Authorization", "Bearer "+newToken["token"]) - mux.ServeHTTP(rw, r) - - if rw.Code != http.StatusOK { - t.Errorf("Shoud return 200") - } - if rw.Body.String() != "ok" { - t.Errorf("Should output ok") - } -} - -func Test_AuthRequestWithoutAuthorizationHeader(t *testing.T) { - url := "/foo" - - mux := beego.NewControllerRegister() - - mux.InsertFilter("*", beego.BeforeRouter, AuthRequest(&Options{ - PrivateKeyPath: "test/jwt.rsa", - PublicKeyPath: "test/jwt.rsa.pub", - WhiteList: []string{"/v1/jwt/issue-token", "/docs"}, - })) - - mux.Add("/foo", &JwtController{}, "get:Foo") - - rw, r := testRequest("GET", url) - mux.ServeHTTP(rw, r) - - if rw.Code != http.StatusUnauthorized { - t.Errorf("Shoud return 401") - } -} diff --git a/plugins/jwt/test/jwt.rsa b/plugins/jwt/test/jwt.rsa deleted file mode 100644 index 8d584fc6..00000000 --- a/plugins/jwt/test/jwt.rsa +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQCdu+23Y/0J/FTQKnIPnxupoOo9/OYCv90DPXN/KLLRAMjYzgcC -DsBST2xVR5jlimI/gyfCpVB62dwpSzzr0cA3MoDhbaGWuTdQUX9zmiLoQ4I7X6h0 -dwyiihOz+CzOMlAg5+qBhiTGcKvIFlfEc1FUcn/tB3PVRG9j6B1Ibz5CnQIDAQAB -AoGAFGg+/i4ai9MwqeoD7c95Bb5C8BgrLgnir0uhCL+cOvwuABbPw01jRoLuEi58 -Mp5vzaXLXByFSA+ts03/qMbvZkDGac5g5kLli5TjHIONMxVBrdfGQ1+OApnaPayN -N+HYjZKs6xao6J5iFqfA0FqzDR9kQhUoeosdQoo1GlxDckECQQDO/0LJrFiLzYWe -qS/DxfAnFu2BlClKZjxRJ3vIkRRaON6HPl8BeJW901bFKG5+WSfO+OwQ9egWaf3X -fFm/oEHRAkEAwxMor4fOkBZbL4KPW7sen169vwnXuYusqj0t3dIeiIVrCigkOMT4 -OvX/63u4CTdXh1D5u/4Z/1HTYH92VCP7DQJAJPxbNKnE0IYSf/z++d4eQP3JxkNw -9Ug7Msz5QycZGd3bdRLh6uNe7iIa+PN2esD3afX0SDuIEqkxoBUp/CFoYQJAUmi3 -mV+/7bLkFrALK+9iwmTdt+TKk4HkEY8C32CysW3biFDo7GqZix79XFfJqWsNuQaG -WdrA1NGWgH+YV3dTyQJAIWEZGAuUXRkQB20LfjGzpsKgQFbqjTisMS0qe3JjnDwu -0JR8sYXapgeEEEisH+OtkZKIfyeFOwoUyNC83bcvgw== ------END RSA PRIVATE KEY----- diff --git a/plugins/jwt/test/jwt.rsa.pub b/plugins/jwt/test/jwt.rsa.pub deleted file mode 100644 index 3fdd8ce7..00000000 --- a/plugins/jwt/test/jwt.rsa.pub +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdu+23Y/0J/FTQKnIPnxupoOo9 -/OYCv90DPXN/KLLRAMjYzgcCDsBST2xVR5jlimI/gyfCpVB62dwpSzzr0cA3MoDh -baGWuTdQUX9zmiLoQ4I7X6h0dwyiihOz+CzOMlAg5+qBhiTGcKvIFlfEc1FUcn/t -B3PVRG9j6B1Ibz5CnQIDAQAB ------END PUBLIC KEY----- diff --git a/router.go b/router.go index 7952663e..16273f58 100644 --- a/router.go +++ b/router.go @@ -87,7 +87,7 @@ func (l *logFilter) Filter(ctx *beecontext.Context) bool { if requestPath == "/favicon.ico" || requestPath == "/robots.txt" { return true } - for prefix := range StaticDir { + for prefix := range BConfig.WebConfig.StaticDir { if strings.HasPrefix(requestPath, prefix) { return true } @@ -183,7 +183,7 @@ func (p *ControllerRegister) Add(pattern string, c ControllerInterface, mappingM } func (p *ControllerRegister) addToRouter(method, pattern string, r *controllerInfo) { - if !RouterCaseSensitive { + if !BConfig.RouterCaseSensitive { pattern = strings.ToLower(pattern) } if t, ok := p.routers[method]; ok { @@ -198,7 +198,7 @@ func (p *ControllerRegister) addToRouter(method, pattern string, r *controllerIn // Include only when the Runmode is dev will generate router file in the router/auto.go from the controller // Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{}) func (p *ControllerRegister) Include(cList ...ControllerInterface) { - if RunMode == "dev" { + if BConfig.RunMode == "dev" { skip := make(map[string]bool, 10) for _, c := range cList { reflectVal := reflect.ValueOf(c) @@ -406,7 +406,7 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter mr.tree = NewTree() mr.pattern = pattern mr.filterFunc = filter - if !RouterCaseSensitive { + if !BConfig.RouterCaseSensitive { pattern = strings.ToLower(pattern) } if len(params) == 0 { @@ -580,8 +580,8 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) w := &responseWriter{rw, false, 0} - if RunMode == "dev" { - w.Header().Set("Server", BeegoServerName) + if BConfig.RunMode == "dev" { + w.Header().Set("Server", BConfig.ServerName) } // init context @@ -592,12 +592,12 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) Output: beecontext.NewOutput(), } context.Output.Context = context - context.Output.EnableGzip = EnableGzip + context.Output.EnableGzip = BConfig.EnableGzip defer p.recoverPanic(context) var urlPath string - if !RouterCaseSensitive { + if !BConfig.RouterCaseSensitive { urlPath = strings.ToLower(r.URL.Path) } else { urlPath = r.URL.Path @@ -646,7 +646,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) } // session init - if SessionOn { + if BConfig.WebConfig.Session.SessionOn { var err error context.Input.CruSession, err = GlobalSessions.SessionStart(w, r) if err != nil { @@ -660,10 +660,10 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) } if r.Method != "GET" && r.Method != "HEAD" { - if CopyRequestBody && !context.Input.IsUpload() { + if BConfig.CopyRequestBody && !context.Input.IsUpload() { context.Input.CopyBody() } - context.Input.ParseFormOrMulitForm(MaxMemory) + context.Input.ParseFormOrMulitForm(BConfig.MaxMemory) } if doFilter(BeforeRouter) { @@ -765,7 +765,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) execController.Prepare() //if XSRF is Enable then check cookie where there has any cookie in the request's cookie _csrf - if EnableXSRF { + if BConfig.WebConfig.EnableXSRF { execController.XSRFToken() if r.Method == "POST" || r.Method == "DELETE" || r.Method == "PUT" || (r.Method == "POST" && (context.Input.Query("_method") == "DELETE" || context.Input.Query("_method") == "PUT")) { @@ -802,7 +802,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) //render template if !w.started && context.Output.Status == 0 { - if AutoRender { + if BConfig.WebConfig.AutoRender { if err := execController.Render(); err != nil { panic(err) } @@ -825,7 +825,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) Admin: timeend := time.Since(starttime) //admin module record QPS - if EnableAdmin { + if BConfig.Listen.AdminEnable { if FilterMonitorFunc(r.Method, r.URL.Path, timeend) { if runrouter != nil { go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runrouter.Name(), timeend) @@ -835,7 +835,7 @@ Admin: } } - if RunMode == "dev" || AccessLogs { + if BConfig.RunMode == "dev" || BConfig.Log.AccessLogs { var devinfo string if findrouter { if routerInfo != nil { @@ -862,10 +862,10 @@ func (p *ControllerRegister) recoverPanic(context *beecontext.Context) { if err == ErrAbort { return } - if !RecoverPanic { + if !BConfig.RecoverPanic { panic(err) } else { - if EnableErrorsShow { + if BConfig.EnableErrorsShow { if _, ok := ErrorMaps[fmt.Sprint(err)]; ok { exception(fmt.Sprint(err), context) return @@ -882,7 +882,7 @@ func (p *ControllerRegister) recoverPanic(context *beecontext.Context) { Critical(fmt.Sprintf("%s:%d", file, line)) stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line)) } - if RunMode == "dev" { + if BConfig.RunMode == "dev" { showErr(err, context, stack) } } diff --git a/staticfile.go b/staticfile.go index e1d88b87..0570006c 100644 --- a/staticfile.go +++ b/staticfile.go @@ -49,7 +49,7 @@ func serverStaticRouter(ctx *context.Context) { } if filePath == "" || fileInfo == nil { - if RunMode == "dev" { + if BConfig.RunMode == "dev" { Warn("Can't find/open the file:", filePath, err) } http.NotFound(ctx.ResponseWriter, ctx.Request) @@ -61,14 +61,14 @@ func serverStaticRouter(ctx *context.Context) { return } - var enableCompress = EnableGzip && isStaticCompress(filePath) + var enableCompress = BConfig.EnableGzip && isStaticCompress(filePath) var acceptEncoding string if enableCompress { acceptEncoding = context.ParseEncoding(ctx.Request) } b, n, sch, err := openFile(filePath, fileInfo, acceptEncoding) if err != nil { - if RunMode == "dev" { + if BConfig.RunMode == "dev" { Warn("Can't compress the file:", filePath, err) } http.NotFound(ctx.ResponseWriter, ctx.Request) @@ -133,7 +133,7 @@ func isOk(s *serveContentHolder, fi os.FileInfo) bool { // isStaticCompress detect static files func isStaticCompress(filePath string) bool { - for _, statExtension := range StaticExtensionsToGzip { + for _, statExtension := range BConfig.WebConfig.StaticExtensionsToGzip { if strings.HasSuffix(strings.ToLower(filePath), strings.ToLower(statExtension)) { return true } @@ -151,7 +151,7 @@ func searchFile(ctx *context.Context) (string, os.FileInfo, error) { if fi, _ := os.Stat(file); fi != nil { return file, fi, nil } - for _, staticDir := range StaticDir { + for _, staticDir := range BConfig.WebConfig.StaticDir { filePath := path.Join(staticDir, requestPath) if fi, _ := os.Stat(filePath); fi != nil { return filePath, fi, nil @@ -160,7 +160,7 @@ func searchFile(ctx *context.Context) (string, os.FileInfo, error) { return "", nil, errors.New(requestPath + " file not find") } - for prefix, staticDir := range StaticDir { + for prefix, staticDir := range BConfig.WebConfig.StaticDir { if len(prefix) == 0 { continue } @@ -193,5 +193,5 @@ func lookupFile(ctx *context.Context) (bool, string, os.FileInfo, error) { if ifi, _ := os.Stat(ifp); ifi != nil && ifi.Mode().IsRegular() { return false, ifp, ifi, err } - return !DirectoryIndex, fp, fi, err + return !BConfig.WebConfig.DirectoryIndex, fp, fi, err } diff --git a/template.go b/template.go index 8822c514..9aac3ea2 100644 --- a/template.go +++ b/template.go @@ -176,7 +176,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp if err != nil { return nil, [][]string{}, err } - reg := regexp.MustCompile(TemplateLeft + "[ ]*template[ ]+\"([^\"]+)\"") + reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*template[ ]+\"([^\"]+)\"") allsub := reg.FindAllStringSubmatch(string(data), -1) for _, m := range allsub { if len(m) == 2 { @@ -197,7 +197,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp } func getTemplate(root, file string, others ...string) (t *template.Template, err error) { - t = template.New(file).Delims(TemplateLeft, TemplateRight).Funcs(beegoTplFuncMap) + t = template.New(file).Delims(BConfig.WebConfig.TemplateLeft, BConfig.WebConfig.TemplateRight).Funcs(beegoTplFuncMap) var submods [][]string t, submods, err = getTplDeep(root, file, "", t) if err != nil { @@ -239,7 +239,7 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others if err != nil { continue } - reg := regexp.MustCompile(TemplateLeft + "[ ]*define[ ]+\"([^\"]+)\"") + reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*define[ ]+\"([^\"]+)\"") allsub := reg.FindAllStringSubmatch(string(data), -1) for _, sub := range allsub { if len(sub) == 2 && sub[1] == m[1] { @@ -262,7 +262,7 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others // SetViewsPath sets view directory path in beego application. func SetViewsPath(path string) *App { - ViewsPath = path + BConfig.WebConfig.ViewsPath = path return BeeApp } @@ -273,7 +273,7 @@ func SetStaticPath(url string, path string) *App { url = "/" + url } url = strings.TrimRight(url, "/") - StaticDir[url] = path + BConfig.WebConfig.StaticDir[url] = path return BeeApp } @@ -283,6 +283,6 @@ func DelStaticPath(url string) *App { url = "/" + url } url = strings.TrimRight(url, "/") - delete(StaticDir, url) + delete(BConfig.WebConfig.StaticDir, url) return BeeApp }