config.go 14.6 KB
Newer Older
A
astaxie 已提交
1
// Copyright 2014 beego Author. All Rights Reserved.
A
astaxie 已提交
2
//
A
astaxie 已提交
3 4 5
// 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
A
astaxie 已提交
6
//
A
astaxie 已提交
7
//      http://www.apache.org/licenses/LICENSE-2.0
A
astaxie 已提交
8
//
A
astaxie 已提交
9 10 11 12 13 14
// 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.

15 16 17
package beego

import (
Y
youngsterxyf 已提交
18
	"fmt"
19
	"os"
20
	"path/filepath"
21
	"strings"
P
Pengfei Xue 已提交
22 23 24

	"github.com/astaxie/beego/config"
	"github.com/astaxie/beego/session"
25
	"github.com/astaxie/beego/utils"
26 27
)

A
astaxie 已提交
28
// Config is the main struct for BConfig
A
astaxie 已提交
29
type Config struct {
A
astaxie 已提交
30 31
	AppName             string //Application name
	RunMode             string //Running Mode: dev | prod
32
	RouterCaseSensitive bool
A
astaxie 已提交
33 34 35 36 37 38 39 40 41
	ServerName          string
	RecoverPanic        bool
	CopyRequestBody     bool
	EnableGzip          bool
	MaxMemory           int64
	EnableErrorsShow    bool
	Listen              Listen
	WebConfig           WebConfig
	Log                 LogConfig
A
astaxie 已提交
42 43
}

A
astaxie 已提交
44
// Listen holds for http and https related config
A
astaxie 已提交
45 46 47 48
type Listen struct {
	Graceful      bool // Graceful means use graceful module to start the server
	ServerTimeOut int64
	ListenTCP4    bool
A
astaxie 已提交
49
	EnableHTTP    bool
A
astaxie 已提交
50 51
	HTTPAddr      string
	HTTPPort      int
A
astaxie 已提交
52
	EnableHTTPS   bool
A
astaxie 已提交
53 54 55 56
	HTTPSAddr     string
	HTTPSPort     int
	HTTPSCertFile string
	HTTPSKeyFile  string
A
astaxie 已提交
57
	EnableAdmin   bool
A
astaxie 已提交
58 59 60 61
	AdminAddr     string
	AdminPort     int
	EnableFcgi    bool
	EnableStdIo   bool // EnableStdIo works with EnableFcgi Use FCGI via standard I/O
A
astaxie 已提交
62 63
}

A
astaxie 已提交
64
// WebConfig holds web related config
A
astaxie 已提交
65 66 67 68
type WebConfig struct {
	AutoRender             bool
	EnableDocs             bool
	FlashName              string
J
JessonChan 已提交
69
	FlashSeparator         string
A
astaxie 已提交
70 71 72 73 74 75 76
	DirectoryIndex         bool
	StaticDir              map[string]string
	StaticExtensionsToGzip []string
	TemplateLeft           string
	TemplateRight          string
	ViewsPath              string
	EnableXSRF             bool
J
JessonChan 已提交
77
	XSRFKey                string
A
astaxie 已提交
78 79
	XSRFExpire             int
	Session                SessionConfig
A
astaxie 已提交
80 81
}

A
astaxie 已提交
82
// SessionConfig holds session related config
A
astaxie 已提交
83 84 85 86 87 88 89 90 91
type SessionConfig struct {
	SessionOn             bool
	SessionProvider       string
	SessionName           string
	SessionGCMaxLifetime  int64
	SessionProviderConfig string
	SessionCookieLifeTime int
	SessionAutoSetCookie  bool
	SessionDomain         string
A
astaxie 已提交
92 93
}

A
astaxie 已提交
94
// LogConfig holds Log related config
A
astaxie 已提交
95 96 97
type LogConfig struct {
	AccessLogs  bool
	FileLineNum bool
A
astaxie 已提交
98
	Outputs     map[string]string // Store Adaptor : config
A
astaxie 已提交
99 100
}

A
astaxie 已提交
101 102
var (
	// BConfig is the default config for Application
A
astaxie 已提交
103
	BConfig *Config
A
astaxie 已提交
104 105
	// AppConfig is the instance of Config, store the config information from file
	AppConfig *beegoAppConfig
C
coseyo 已提交
106 107
	// AppPath is the absolute path to the app
	AppPath string
A
astaxie 已提交
108 109
	// GlobalSessions is the instance for the session manager
	GlobalSessions *session.Manager
Y
youngsterxyf 已提交
110

111 112 113 114
	// appConfigPath is the path to the config files
	appConfigPath string
	// appConfigProvider is the provider for the config, default is ini
	appConfigProvider = "ini"
A
astaxie 已提交
115
)
A
astaxie 已提交
116

A
astaxie 已提交
117
func init() {
C
coseyo 已提交
118 119
	AppPath, _ = filepath.Abs(filepath.Dir(os.Args[0]))

120
	os.Chdir(AppPath)
Y
youngsterxyf 已提交
121

A
astaxie 已提交
122
	BConfig = &Config{
A
astaxie 已提交
123
		AppName:             "beego",
124
		RunMode:             DEV,
A
astaxie 已提交
125 126 127 128 129 130 131 132 133 134 135
		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,
A
astaxie 已提交
136
			EnableHTTP:    true,
A
astaxie 已提交
137 138
			HTTPAddr:      "",
			HTTPPort:      8080,
A
astaxie 已提交
139
			EnableHTTPS:   false,
A
astaxie 已提交
140 141 142 143
			HTTPSAddr:     "",
			HTTPSPort:     10443,
			HTTPSCertFile: "",
			HTTPSKeyFile:  "",
A
astaxie 已提交
144
			EnableAdmin:   false,
A
astaxie 已提交
145 146 147 148 149 150 151 152 153
			AdminAddr:     "",
			AdminPort:     8088,
			EnableFcgi:    false,
			EnableStdIo:   false,
		},
		WebConfig: WebConfig{
			AutoRender:             true,
			EnableDocs:             false,
			FlashName:              "BEEGO_FLASH",
J
JessonChan 已提交
154
			FlashSeparator:         "BEEGOFLASH",
A
astaxie 已提交
155 156 157 158 159 160 161
			DirectoryIndex:         false,
			StaticDir:              map[string]string{"/static": "static"},
			StaticExtensionsToGzip: []string{".css", ".js"},
			TemplateLeft:           "{{",
			TemplateRight:          "}}",
			ViewsPath:              "views",
			EnableXSRF:             false,
J
JessonChan 已提交
162
			XSRFKey:                "beegoxsrf",
A
astaxie 已提交
163 164 165 166 167 168 169
			XSRFExpire:             0,
			Session: SessionConfig{
				SessionOn:             false,
				SessionProvider:       "memory",
				SessionName:           "beegosessionID",
				SessionGCMaxLifetime:  3600,
				SessionProviderConfig: "",
170
				SessionCookieLifeTime: 0, //set cookie default is the browser life
A
astaxie 已提交
171 172 173 174 175 176 177
				SessionAutoSetCookie:  true,
				SessionDomain:         "",
			},
		},
		Log: LogConfig{
			AccessLogs:  false,
			FileLineNum: true,
A
astaxie 已提交
178
			Outputs:     map[string]string{"console": ""},
A
astaxie 已提交
179
		},
A
astaxie 已提交
180
	}
Y
youngsterxyf 已提交
181

182 183
	appConfigPath = filepath.Join(AppPath, "conf", "app.conf")
	if !utils.FileExists(appConfigPath) {
184
		AppConfig = &beegoAppConfig{innerConfig: config.NewFakeConfig()}
Y
youngsterxyf 已提交
185 186 187
		return
	}

Y
ysqi 已提交
188 189 190
	if err := parseConfig(appConfigPath); err != nil {
		panic(err)
	}
Y
youngsterxyf 已提交
191 192
}

A
astaxie 已提交
193
// now only support ini, next will support json.
Y
youngsterxyf 已提交
194
func parseConfig(appConfigPath string) (err error) {
195
	AppConfig, err = newAppConfig(appConfigProvider, appConfigPath)
A
astaxie 已提交
196 197 198
	if err != nil {
		return err
	}
199
	// set the run mode first
F
fuxiaohei 已提交
200
	if envRunMode := os.Getenv("BEEGO_RUNMODE"); envRunMode != "" {
A
astaxie 已提交
201
		BConfig.RunMode = envRunMode
202 203
	} else if runMode := AppConfig.String("RunMode"); runMode != "" {
		BConfig.RunMode = runMode
A
astaxie 已提交
204
	}
205

A
astaxie 已提交
206 207 208
	BConfig.AppName = AppConfig.DefaultString("AppName", BConfig.AppName)
	BConfig.RecoverPanic = AppConfig.DefaultBool("RecoverPanic", BConfig.RecoverPanic)
	BConfig.RouterCaseSensitive = AppConfig.DefaultBool("RouterCaseSensitive", BConfig.RouterCaseSensitive)
A
astaxie 已提交
209
	BConfig.ServerName = AppConfig.DefaultString("ServerName", BConfig.ServerName)
A
astaxie 已提交
210 211 212 213 214
	BConfig.EnableGzip = AppConfig.DefaultBool("EnableGzip", BConfig.EnableGzip)
	BConfig.EnableErrorsShow = AppConfig.DefaultBool("EnableErrorsShow", BConfig.EnableErrorsShow)
	BConfig.CopyRequestBody = AppConfig.DefaultBool("CopyRequestBody", BConfig.CopyRequestBody)
	BConfig.MaxMemory = AppConfig.DefaultInt64("MaxMemory", BConfig.MaxMemory)
	BConfig.Listen.Graceful = AppConfig.DefaultBool("Graceful", BConfig.Listen.Graceful)
A
astaxie 已提交
215
	BConfig.Listen.HTTPAddr = AppConfig.String("HTTPAddr")
A
astaxie 已提交
216 217
	BConfig.Listen.HTTPPort = AppConfig.DefaultInt("HTTPPort", BConfig.Listen.HTTPPort)
	BConfig.Listen.ListenTCP4 = AppConfig.DefaultBool("ListenTCP4", BConfig.Listen.ListenTCP4)
A
astaxie 已提交
218 219
	BConfig.Listen.EnableHTTP = AppConfig.DefaultBool("EnableHTTP", BConfig.Listen.EnableHTTP)
	BConfig.Listen.EnableHTTPS = AppConfig.DefaultBool("EnableHTTPS", BConfig.Listen.EnableHTTPS)
A
astaxie 已提交
220
	BConfig.Listen.HTTPSAddr = AppConfig.DefaultString("HTTPSAddr", BConfig.Listen.HTTPSAddr)
A
astaxie 已提交
221
	BConfig.Listen.HTTPSPort = AppConfig.DefaultInt("HTTPSPort", BConfig.Listen.HTTPSPort)
A
astaxie 已提交
222 223 224 225 226
	BConfig.Listen.HTTPSCertFile = AppConfig.DefaultString("HTTPSCertFile", BConfig.Listen.HTTPSCertFile)
	BConfig.Listen.HTTPSKeyFile = AppConfig.DefaultString("HTTPSKeyFile", BConfig.Listen.HTTPSKeyFile)
	BConfig.Listen.EnableAdmin = AppConfig.DefaultBool("EnableAdmin", BConfig.Listen.EnableAdmin)
	BConfig.Listen.AdminAddr = AppConfig.DefaultString("AdminAddr", BConfig.Listen.AdminAddr)
	BConfig.Listen.AdminPort = AppConfig.DefaultInt("AdminPort", BConfig.Listen.AdminPort)
A
astaxie 已提交
227
	BConfig.Listen.EnableFcgi = AppConfig.DefaultBool("EnableFcgi", BConfig.Listen.EnableFcgi)
A
astaxie 已提交
228
	BConfig.Listen.EnableStdIo = AppConfig.DefaultBool("EnableStdIo", BConfig.Listen.EnableStdIo)
A
astaxie 已提交
229
	BConfig.Listen.ServerTimeOut = AppConfig.DefaultInt64("ServerTimeOut", BConfig.Listen.ServerTimeOut)
A
astaxie 已提交
230 231 232
	BConfig.WebConfig.AutoRender = AppConfig.DefaultBool("AutoRender", BConfig.WebConfig.AutoRender)
	BConfig.WebConfig.ViewsPath = AppConfig.DefaultString("ViewsPath", BConfig.WebConfig.ViewsPath)
	BConfig.WebConfig.DirectoryIndex = AppConfig.DefaultBool("DirectoryIndex", BConfig.WebConfig.DirectoryIndex)
A
astaxie 已提交
233
	BConfig.WebConfig.FlashName = AppConfig.DefaultString("FlashName", BConfig.WebConfig.FlashName)
J
JessonChan 已提交
234
	BConfig.WebConfig.FlashSeparator = AppConfig.DefaultString("FlashSeparator", BConfig.WebConfig.FlashSeparator)
A
astaxie 已提交
235
	BConfig.WebConfig.EnableDocs = AppConfig.DefaultBool("EnableDocs", BConfig.WebConfig.EnableDocs)
J
JessonChan 已提交
236
	BConfig.WebConfig.XSRFKey = AppConfig.DefaultString("XSRFKEY", BConfig.WebConfig.XSRFKey)
A
astaxie 已提交
237 238 239 240 241 242 243 244 245 246
	BConfig.WebConfig.EnableXSRF = AppConfig.DefaultBool("EnableXSRF", BConfig.WebConfig.EnableXSRF)
	BConfig.WebConfig.XSRFExpire = AppConfig.DefaultInt("XSRFExpire", BConfig.WebConfig.XSRFExpire)
	BConfig.WebConfig.TemplateLeft = AppConfig.DefaultString("TemplateLeft", BConfig.WebConfig.TemplateLeft)
	BConfig.WebConfig.TemplateRight = AppConfig.DefaultString("TemplateRight", BConfig.WebConfig.TemplateRight)
	BConfig.WebConfig.Session.SessionOn = AppConfig.DefaultBool("SessionOn", BConfig.WebConfig.Session.SessionOn)
	BConfig.WebConfig.Session.SessionProvider = AppConfig.DefaultString("SessionProvider", BConfig.WebConfig.Session.SessionProvider)
	BConfig.WebConfig.Session.SessionName = AppConfig.DefaultString("SessionName", BConfig.WebConfig.Session.SessionName)
	BConfig.WebConfig.Session.SessionProviderConfig = AppConfig.DefaultString("SessionProviderConfig", BConfig.WebConfig.Session.SessionProviderConfig)
	BConfig.WebConfig.Session.SessionGCMaxLifetime = AppConfig.DefaultInt64("SessionGCMaxLifetime", BConfig.WebConfig.Session.SessionGCMaxLifetime)
	BConfig.WebConfig.Session.SessionCookieLifeTime = AppConfig.DefaultInt("SessionCookieLifeTime", BConfig.WebConfig.Session.SessionCookieLifeTime)
A
astaxie 已提交
247 248
	BConfig.WebConfig.Session.SessionAutoSetCookie = AppConfig.DefaultBool("SessionAutoSetCookie", BConfig.WebConfig.Session.SessionAutoSetCookie)
	BConfig.WebConfig.Session.SessionDomain = AppConfig.DefaultString("SessionDomain", BConfig.WebConfig.Session.SessionDomain)
Y
youngsterxyf 已提交
249 250
	BConfig.Log.AccessLogs = AppConfig.DefaultBool("LogAccessLogs", BConfig.Log.AccessLogs)
	BConfig.Log.FileLineNum = AppConfig.DefaultBool("LogFileLineNum", BConfig.Log.FileLineNum)
A
astaxie 已提交
251

A
astaxie 已提交
252
	if sd := AppConfig.String("StaticDir"); sd != "" {
A
astaxie 已提交
253 254
		for k := range BConfig.WebConfig.StaticDir {
			delete(BConfig.WebConfig.StaticDir, k)
A
astaxie 已提交
255 256 257 258
		}
		sds := strings.Fields(sd)
		for _, v := range sds {
			if url2fsmap := strings.SplitN(v, ":", 2); len(url2fsmap) == 2 {
A
astaxie 已提交
259
				BConfig.WebConfig.StaticDir["/"+strings.TrimRight(url2fsmap[0], "/")] = url2fsmap[1]
A
astaxie 已提交
260
			} else {
A
astaxie 已提交
261
				BConfig.WebConfig.StaticDir["/"+strings.TrimRight(url2fsmap[0], "/")] = url2fsmap[0]
262 263
			}
		}
A
astaxie 已提交
264
	}
265

A
astaxie 已提交
266 267
	if sgz := AppConfig.String("StaticExtensionsToGzip"); sgz != "" {
		extensions := strings.Split(sgz, ",")
J
JessonChan 已提交
268
		fileExts := []string{}
J
JessonChan 已提交
269 270 271 272
		for _, ext := range extensions {
			ext = strings.TrimSpace(ext)
			if ext == "" {
				continue
F
Francois 已提交
273
			}
J
JessonChan 已提交
274 275 276
			if !strings.HasPrefix(ext, ".") {
				ext = "." + ext
			}
J
JessonChan 已提交
277 278 279
			fileExts = append(fileExts, ext)
		}
		if len(fileExts) > 0 {
A
astaxie 已提交
280
			BConfig.WebConfig.StaticExtensionsToGzip = fileExts
F
Francois 已提交
281
		}
A
astaxie 已提交
282
	}
Y
youngsterxyf 已提交
283 284 285 286 287 288 289 290 291 292 293 294 295

	if lo := AppConfig.String("LogOutputs"); lo != "" {
		los := strings.Split(lo, ";")
		for _, v := range los {
			if logType2Config := strings.SplitN(v, ",", 2); len(logType2Config) == 2 {
				BConfig.Log.Outputs[logType2Config[0]] = logType2Config[1]
			} else {
				continue
			}
		}
	}

	//init log
Y
youngsterxyf 已提交
296
	BeeLogger.Reset()
Y
youngsterxyf 已提交
297 298 299 300 301 302 303 304
	for adaptor, config := range BConfig.Log.Outputs {
		err = BeeLogger.SetLogger(adaptor, config)
		if err != nil {
			fmt.Printf("%s with the config `%s` got err:%s\n", adaptor, config, err)
		}
	}
	SetLogFuncCall(BConfig.Log.FileLineNum)

A
astaxie 已提交
305
	return nil
306
}
A
astaxie 已提交
307

Y
youngsterxyf 已提交
308
// LoadAppConfig allow developer to apply a config file
309
func LoadAppConfig(adapterName, configPath string) error {
Y
youngsterxyf 已提交
310 311 312 313
	absConfigPath, err := filepath.Abs(configPath)
	if err != nil {
		return err
	}
Y
youngsterxyf 已提交
314 315

	if !utils.FileExists(absConfigPath) {
A
astaxie 已提交
316
		return fmt.Errorf("the target config file: %s don't exist", configPath)
Y
youngsterxyf 已提交
317 318
	}

319 320
	appConfigPath = absConfigPath
	appConfigProvider = adapterName
Y
youngsterxyf 已提交
321

322
	return parseConfig(appConfigPath)
Y
youngsterxyf 已提交
323 324
}

A
astaxie 已提交
325 326 327 328
type beegoAppConfig struct {
	innerConfig config.Configer
}

329 330
func newAppConfig(appConfigProvider, appConfigPath string) (*beegoAppConfig, error) {
	ac, err := config.NewConfig(appConfigProvider, appConfigPath)
A
astaxie 已提交
331 332 333
	if err != nil {
		return nil, err
	}
F
fuxiaohei 已提交
334
	return &beegoAppConfig{ac}, nil
A
astaxie 已提交
335 336 337
}

func (b *beegoAppConfig) Set(key, val string) error {
F
fuxiaohei 已提交
338
	if err := b.innerConfig.Set(BConfig.RunMode+"::"+key, val); err != nil {
A
astaxie 已提交
339 340 341 342 343 344
		return err
	}
	return b.innerConfig.Set(key, val)
}

func (b *beegoAppConfig) String(key string) string {
F
fuxiaohei 已提交
345 346
	if v := b.innerConfig.String(BConfig.RunMode + "::" + key); v != "" {
		return v
A
astaxie 已提交
347
	}
F
fuxiaohei 已提交
348
	return b.innerConfig.String(key)
A
astaxie 已提交
349 350 351
}

func (b *beegoAppConfig) Strings(key string) []string {
J
JessonChan 已提交
352
	if v := b.innerConfig.Strings(BConfig.RunMode + "::" + key); len(v) > 0 {
F
fud 已提交
353
		return v
A
astaxie 已提交
354
	}
F
fuxiaohei 已提交
355
	return b.innerConfig.Strings(key)
A
astaxie 已提交
356 357 358
}

func (b *beegoAppConfig) Int(key string) (int, error) {
F
fuxiaohei 已提交
359 360
	if v, err := b.innerConfig.Int(BConfig.RunMode + "::" + key); err == nil {
		return v, nil
A
astaxie 已提交
361
	}
F
fuxiaohei 已提交
362
	return b.innerConfig.Int(key)
A
astaxie 已提交
363 364 365
}

func (b *beegoAppConfig) Int64(key string) (int64, error) {
F
fuxiaohei 已提交
366 367
	if v, err := b.innerConfig.Int64(BConfig.RunMode + "::" + key); err == nil {
		return v, nil
A
astaxie 已提交
368
	}
F
fuxiaohei 已提交
369
	return b.innerConfig.Int64(key)
A
astaxie 已提交
370 371 372
}

func (b *beegoAppConfig) Bool(key string) (bool, error) {
F
fuxiaohei 已提交
373 374
	if v, err := b.innerConfig.Bool(BConfig.RunMode + "::" + key); err == nil {
		return v, nil
A
astaxie 已提交
375
	}
F
fuxiaohei 已提交
376
	return b.innerConfig.Bool(key)
A
astaxie 已提交
377 378 379
}

func (b *beegoAppConfig) Float(key string) (float64, error) {
F
fuxiaohei 已提交
380 381
	if v, err := b.innerConfig.Float(BConfig.RunMode + "::" + key); err == nil {
		return v, nil
A
astaxie 已提交
382
	}
F
fuxiaohei 已提交
383
	return b.innerConfig.Float(key)
A
astaxie 已提交
384 385
}

386
func (b *beegoAppConfig) DefaultString(key string, defaultVal string) string {
F
fuxiaohei 已提交
387
	if v := b.String(key); v != "" {
A
astaxie 已提交
388 389
		return v
	}
390
	return defaultVal
A
astaxie 已提交
391 392
}

393
func (b *beegoAppConfig) DefaultStrings(key string, defaultVal []string) []string {
F
fuxiaohei 已提交
394
	if v := b.Strings(key); len(v) != 0 {
A
astaxie 已提交
395 396
		return v
	}
397
	return defaultVal
A
astaxie 已提交
398 399
}

400
func (b *beegoAppConfig) DefaultInt(key string, defaultVal int) int {
F
fuxiaohei 已提交
401
	if v, err := b.Int(key); err == nil {
A
astaxie 已提交
402 403
		return v
	}
404
	return defaultVal
A
astaxie 已提交
405 406
}

407
func (b *beegoAppConfig) DefaultInt64(key string, defaultVal int64) int64 {
F
fuxiaohei 已提交
408
	if v, err := b.Int64(key); err == nil {
A
astaxie 已提交
409 410
		return v
	}
411
	return defaultVal
A
astaxie 已提交
412 413
}

414
func (b *beegoAppConfig) DefaultBool(key string, defaultVal bool) bool {
F
fuxiaohei 已提交
415
	if v, err := b.Bool(key); err == nil {
A
astaxie 已提交
416 417
		return v
	}
418
	return defaultVal
A
astaxie 已提交
419 420
}

421
func (b *beegoAppConfig) DefaultFloat(key string, defaultVal float64) float64 {
F
fuxiaohei 已提交
422
	if v, err := b.Float(key); err == nil {
A
astaxie 已提交
423 424
		return v
	}
425
	return defaultVal
A
astaxie 已提交
426 427 428 429 430 431 432 433 434 435 436 437 438
}

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)
}