123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- // 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 beego
- import (
- "fmt"
- "os"
- "path/filepath"
- "reflect"
- "runtime"
- "strings"
- "github.com/astaxie/beego/config"
- "github.com/astaxie/beego/context"
- "github.com/astaxie/beego/logs"
- "github.com/astaxie/beego/session"
- "github.com/astaxie/beego/utils"
- )
- // Config is the main struct for BConfig
- type Config struct {
- AppName string //Application name
- RunMode string //Running Mode: dev | prod
- RouterCaseSensitive bool
- ServerName string
- RecoverPanic bool
- RecoverFunc func(*context.Context)
- CopyRequestBody bool
- EnableGzip bool
- MaxMemory int64
- EnableErrorsShow bool
- EnableErrorsRender bool
- Listen Listen
- WebConfig WebConfig
- Log LogConfig
- }
- // Listen holds for http and https related config
- type Listen struct {
- Graceful bool // Graceful means use graceful module to start the server
- ServerTimeOut int64
- ListenTCP4 bool
- EnableHTTP bool
- HTTPAddr string
- HTTPPort int
- EnableHTTPS bool
- HTTPSAddr string
- HTTPSPort int
- HTTPSCertFile string
- HTTPSKeyFile string
- EnableAdmin bool
- AdminAddr string
- AdminPort int
- EnableFcgi bool
- EnableStdIo bool // EnableStdIo works with EnableFcgi Use FCGI via standard I/O
- }
- // WebConfig holds web related config
- type WebConfig struct {
- AutoRender bool
- EnableDocs bool
- FlashName string
- FlashSeparator string
- DirectoryIndex bool
- StaticDir map[string]string
- StaticExtensionsToGzip []string
- TemplateLeft string
- TemplateRight string
- ViewsPath string
- EnableXSRF bool
- XSRFKey string
- XSRFExpire int
- Session SessionConfig
- }
- // SessionConfig holds session related config
- type SessionConfig struct {
- SessionOn bool
- SessionProvider string
- SessionName string
- SessionGCMaxLifetime int64
- SessionProviderConfig string
- SessionCookieLifeTime int
- SessionAutoSetCookie bool
- SessionDomain string
- SessionDisableHTTPOnly bool // used to allow for cross domain cookies/javascript cookies.
- SessionEnableSidInHTTPHeader bool // enable store/get the sessionId into/from http headers
- SessionNameInHTTPHeader string
- SessionEnableSidInURLQuery bool // enable get the sessionId from Url Query params
- }
- // LogConfig holds Log related config
- type LogConfig struct {
- AccessLogs bool
- FileLineNum bool
- Outputs map[string]string // Store Adaptor : config
- }
- var (
- // BConfig is the default config for Application
- BConfig *Config
- // AppConfig is the instance of Config, store the config information from file
- AppConfig *beegoAppConfig
- // AppPath is the absolute path to the app
- AppPath string
- // GlobalSessions is the instance for the session manager
- GlobalSessions *session.Manager
- // appConfigPath is the path to the config files
- appConfigPath string
- // appConfigProvider is the provider for the config, default is ini
- appConfigProvider = "ini"
- )
- func init() {
- BConfig = newBConfig()
- var err error
- if AppPath, err = filepath.Abs(filepath.Dir(os.Args[0])); err != nil {
- panic(err)
- }
- workPath, err := os.Getwd()
- if err != nil {
- panic(err)
- }
- appConfigPath = filepath.Join(workPath, "conf", "app.conf")
- if !utils.FileExists(appConfigPath) {
- appConfigPath = filepath.Join(AppPath, "conf", "app.conf")
- if !utils.FileExists(appConfigPath) {
- AppConfig = &beegoAppConfig{innerConfig: config.NewFakeConfig()}
- return
- }
- }
- if err = parseConfig(appConfigPath); err != nil {
- panic(err)
- }
- }
- func recoverPanic(ctx *context.Context) {
- if err := recover(); err != nil {
- if err == ErrAbort {
- return
- }
- if !BConfig.RecoverPanic {
- panic(err)
- }
- if BConfig.EnableErrorsShow {
- if _, ok := ErrorMaps[fmt.Sprint(err)]; ok {
- exception(fmt.Sprint(err), ctx)
- return
- }
- }
- var stack string
- logs.Critical("the request url is ", ctx.Input.URL())
- logs.Critical("Handler crashed with error", err)
- for i := 1; ; i++ {
- _, file, line, ok := runtime.Caller(i)
- if !ok {
- break
- }
- logs.Critical(fmt.Sprintf("%s:%d", file, line))
- stack = stack + fmt.Sprintln(fmt.Sprintf("%s:%d", file, line))
- }
- if BConfig.RunMode == DEV && BConfig.EnableErrorsRender {
- showErr(err, ctx, stack)
- }
- }
- }
- func newBConfig() *Config {
- return &Config{
- AppName: "beego",
- RunMode: DEV,
- RouterCaseSensitive: true,
- ServerName: "beegoServer:" + VERSION,
- RecoverPanic: true,
- RecoverFunc: recoverPanic,
- CopyRequestBody: false,
- EnableGzip: false,
- MaxMemory: 1 << 26, //64MB
- EnableErrorsShow: true,
- EnableErrorsRender: true,
- Listen: Listen{
- Graceful: false,
- ServerTimeOut: 0,
- ListenTCP4: false,
- EnableHTTP: true,
- HTTPAddr: "",
- HTTPPort: 8080,
- EnableHTTPS: false,
- HTTPSAddr: "",
- HTTPSPort: 10443,
- HTTPSCertFile: "",
- HTTPSKeyFile: "",
- EnableAdmin: false,
- AdminAddr: "",
- AdminPort: 8088,
- EnableFcgi: false,
- EnableStdIo: false,
- },
- WebConfig: WebConfig{
- AutoRender: true,
- EnableDocs: false,
- FlashName: "BEEGO_FLASH",
- FlashSeparator: "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: "",
- SessionDisableHTTPOnly: false,
- SessionCookieLifeTime: 0, //set cookie default is the browser life
- SessionAutoSetCookie: true,
- SessionDomain: "",
- SessionEnableSidInHTTPHeader: false, // enable store/get the sessionId into/from http headers
- SessionNameInHTTPHeader: "Beegosessionid",
- SessionEnableSidInURLQuery: false, // enable get the sessionId from Url Query params
- },
- },
- Log: LogConfig{
- AccessLogs: false,
- FileLineNum: true,
- Outputs: map[string]string{"console": ""},
- },
- }
- }
- // now only support ini, next will support json.
- func parseConfig(appConfigPath string) (err error) {
- AppConfig, err = newAppConfig(appConfigProvider, appConfigPath)
- if err != nil {
- return err
- }
- return assignConfig(AppConfig)
- }
- func assignConfig(ac config.Configer) error {
- for _, i := range []interface{}{BConfig, &BConfig.Listen, &BConfig.WebConfig, &BConfig.Log, &BConfig.WebConfig.Session} {
- assignSingleConfig(i, ac)
- }
- // set the run mode first
- if envRunMode := os.Getenv("BEEGO_RUNMODE"); envRunMode != "" {
- BConfig.RunMode = envRunMode
- } else if runMode := ac.String("RunMode"); runMode != "" {
- BConfig.RunMode = runMode
- }
- if sd := ac.String("StaticDir"); sd != "" {
- BConfig.WebConfig.StaticDir = map[string]string{}
- sds := strings.Fields(sd)
- for _, v := range sds {
- if url2fsmap := strings.SplitN(v, ":", 2); len(url2fsmap) == 2 {
- BConfig.WebConfig.StaticDir["/"+strings.Trim(url2fsmap[0], "/")] = url2fsmap[1]
- } else {
- BConfig.WebConfig.StaticDir["/"+strings.Trim(url2fsmap[0], "/")] = url2fsmap[0]
- }
- }
- }
- if sgz := ac.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 lo := ac.String("LogOutputs"); lo != "" {
- // if lo is not nil or empty
- // means user has set his own LogOutputs
- // clear the default setting to BConfig.Log.Outputs
- BConfig.Log.Outputs = make(map[string]string)
- los := strings.Split(lo, ";")
- for _, v := range los {
- if logType2Config := strings.SplitN(v, ",", 2); len(logType2Config) == 2 {
- BConfig.Log.Outputs[logType2Config[0]] = logType2Config[1]
- } else {
- continue
- }
- }
- }
- //init log
- logs.Reset()
- for adaptor, config := range BConfig.Log.Outputs {
- err := logs.SetLogger(adaptor, config)
- if err != nil {
- fmt.Fprintln(os.Stderr, fmt.Sprintf("%s with the config %q got err:%s", adaptor, config, err.Error()))
- }
- }
- logs.SetLogFuncCall(BConfig.Log.FileLineNum)
- return nil
- }
- func assignSingleConfig(p interface{}, ac config.Configer) {
- pt := reflect.TypeOf(p)
- if pt.Kind() != reflect.Ptr {
- return
- }
- pt = pt.Elem()
- if pt.Kind() != reflect.Struct {
- return
- }
- pv := reflect.ValueOf(p).Elem()
- for i := 0; i < pt.NumField(); i++ {
- pf := pv.Field(i)
- if !pf.CanSet() {
- continue
- }
- name := pt.Field(i).Name
- switch pf.Kind() {
- case reflect.String:
- pf.SetString(ac.DefaultString(name, pf.String()))
- case reflect.Int, reflect.Int64:
- pf.SetInt(int64(ac.DefaultInt64(name, pf.Int())))
- case reflect.Bool:
- pf.SetBool(ac.DefaultBool(name, pf.Bool()))
- case reflect.Struct:
- default:
- //do nothing here
- }
- }
- }
- // LoadAppConfig allow developer to apply a config file
- func LoadAppConfig(adapterName, configPath string) error {
- absConfigPath, err := filepath.Abs(configPath)
- if err != nil {
- return err
- }
- if !utils.FileExists(absConfigPath) {
- return fmt.Errorf("the target config file: %s don't exist", configPath)
- }
- appConfigPath = absConfigPath
- appConfigProvider = adapterName
- return parseConfig(appConfigPath)
- }
- type beegoAppConfig struct {
- innerConfig config.Configer
- }
- func newAppConfig(appConfigProvider, appConfigPath string) (*beegoAppConfig, error) {
- ac, err := config.NewConfig(appConfigProvider, appConfigPath)
- if err != nil {
- return nil, err
- }
- return &beegoAppConfig{ac}, nil
- }
- func (b *beegoAppConfig) Set(key, val string) error {
- if err := b.innerConfig.Set(BConfig.RunMode+"::"+key, val); err != nil {
- return err
- }
- return b.innerConfig.Set(key, val)
- }
- func (b *beegoAppConfig) String(key string) string {
- if v := b.innerConfig.String(BConfig.RunMode + "::" + key); v != "" {
- return v
- }
- return b.innerConfig.String(key)
- }
- func (b *beegoAppConfig) Strings(key string) []string {
- if v := b.innerConfig.Strings(BConfig.RunMode + "::" + key); len(v) > 0 {
- return v
- }
- return b.innerConfig.Strings(key)
- }
- func (b *beegoAppConfig) Int(key string) (int, error) {
- if v, err := b.innerConfig.Int(BConfig.RunMode + "::" + key); err == nil {
- return v, nil
- }
- return b.innerConfig.Int(key)
- }
- func (b *beegoAppConfig) Int64(key string) (int64, error) {
- if v, err := b.innerConfig.Int64(BConfig.RunMode + "::" + key); err == nil {
- return v, nil
- }
- return b.innerConfig.Int64(key)
- }
- func (b *beegoAppConfig) Bool(key string) (bool, error) {
- if v, err := b.innerConfig.Bool(BConfig.RunMode + "::" + key); err == nil {
- return v, nil
- }
- return b.innerConfig.Bool(key)
- }
- func (b *beegoAppConfig) Float(key string) (float64, error) {
- if v, err := b.innerConfig.Float(BConfig.RunMode + "::" + key); err == nil {
- return v, nil
- }
- return b.innerConfig.Float(key)
- }
- func (b *beegoAppConfig) DefaultString(key string, defaultVal string) string {
- if v := b.String(key); v != "" {
- return v
- }
- return defaultVal
- }
- func (b *beegoAppConfig) DefaultStrings(key string, defaultVal []string) []string {
- if v := b.Strings(key); len(v) != 0 {
- return v
- }
- return defaultVal
- }
- func (b *beegoAppConfig) DefaultInt(key string, defaultVal int) int {
- if v, err := b.Int(key); err == nil {
- return v
- }
- return defaultVal
- }
- func (b *beegoAppConfig) DefaultInt64(key string, defaultVal int64) int64 {
- if v, err := b.Int64(key); err == nil {
- return v
- }
- return defaultVal
- }
- func (b *beegoAppConfig) DefaultBool(key string, defaultVal bool) bool {
- if v, err := b.Bool(key); err == nil {
- return v
- }
- return defaultVal
- }
- func (b *beegoAppConfig) DefaultFloat(key string, defaultVal float64) float64 {
- if v, err := b.Float(key); err == nil {
- return v
- }
- return defaultVal
- }
- func (b *beegoAppConfig) DIY(key string) (interface{}, error) {
- return b.innerConfig.DIY(key)
- }
- func (b *beegoAppConfig) GetSection(section string) (map[string]string, error) {
- return b.innerConfig.GetSection(section)
- }
- func (b *beegoAppConfig) SaveConfigFile(filename string) error {
- return b.innerConfig.SaveConfigFile(filename)
- }
|