config.go 14.8 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 18 19
package beego

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

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

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

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

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

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

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

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

C
coseyo 已提交
114
	workPath string
115 116 117 118
	// appConfigPath is the path to the config files
	appConfigPath string
	// appConfigProvider is the provider for the config, default is ini
	appConfigProvider = "ini"
A
astaxie 已提交
119
)
A
astaxie 已提交
120

A
astaxie 已提交
121
func init() {
C
coseyo 已提交
122 123 124 125
	AppPath, _ = filepath.Abs(filepath.Dir(os.Args[0]))
	workPath, _ = os.Getwd()
	workPath, _ = filepath.Abs(workPath)

Y
youngsterxyf 已提交
126 127 128 129
	if workPath != AppPath {
		os.Chdir(AppPath)
	}

A
astaxie 已提交
130
	BConfig = &Config{
A
astaxie 已提交
131
		AppName:             "beego",
132
		RunMode:             DEV,
A
astaxie 已提交
133 134 135 136 137 138 139 140 141 142 143
		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 已提交
144
			EnableHTTP:    true,
A
astaxie 已提交
145 146
			HTTPAddr:      "",
			HTTPPort:      8080,
A
astaxie 已提交
147
			EnableHTTPS:   false,
A
astaxie 已提交
148 149 150 151
			HTTPSAddr:     "",
			HTTPSPort:     10443,
			HTTPSCertFile: "",
			HTTPSKeyFile:  "",
A
astaxie 已提交
152
			EnableAdmin:   false,
A
astaxie 已提交
153 154 155 156 157 158 159 160 161
			AdminAddr:     "",
			AdminPort:     8088,
			EnableFcgi:    false,
			EnableStdIo:   false,
		},
		WebConfig: WebConfig{
			AutoRender:             true,
			EnableDocs:             false,
			FlashName:              "BEEGO_FLASH",
J
JessonChan 已提交
162
			FlashSeparator:         "BEEGOFLASH",
A
astaxie 已提交
163 164 165 166 167 168 169
			DirectoryIndex:         false,
			StaticDir:              map[string]string{"/static": "static"},
			StaticExtensionsToGzip: []string{".css", ".js"},
			TemplateLeft:           "{{",
			TemplateRight:          "}}",
			ViewsPath:              "views",
			EnableXSRF:             false,
J
JessonChan 已提交
170
			XSRFKey:                "beegoxsrf",
A
astaxie 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
			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,
A
astaxie 已提交
186
			Outputs:     map[string]string{"console": ""},
A
astaxie 已提交
187
		},
A
astaxie 已提交
188
	}
Y
youngsterxyf 已提交
189

190 191
	appConfigPath = filepath.Join(AppPath, "conf", "app.conf")
	if !utils.FileExists(appConfigPath) {
Y
youngsterxyf 已提交
192 193 194 195
		AppConfig = &beegoAppConfig{config.NewFakeConfig()}
		return
	}

196
	parseConfig(appConfigPath)
Y
youngsterxyf 已提交
197 198
}

A
astaxie 已提交
199
// now only support ini, next will support json.
Y
youngsterxyf 已提交
200
func parseConfig(appConfigPath string) (err error) {
201
	AppConfig, err = newAppConfig(appConfigProvider, appConfigPath)
A
astaxie 已提交
202 203 204
	if err != nil {
		return err
	}
A
astaxie 已提交
205
	// set the runmode first
F
fuxiaohei 已提交
206
	if envRunMode := os.Getenv("BEEGO_RUNMODE"); envRunMode != "" {
A
astaxie 已提交
207
		BConfig.RunMode = envRunMode
208
	} else if runmode := AppConfig.String("RunMode"); runmode != "" {
A
astaxie 已提交
209
		BConfig.RunMode = runmode
A
astaxie 已提交
210
	}
211

A
astaxie 已提交
212 213 214
	BConfig.AppName = AppConfig.DefaultString("AppName", BConfig.AppName)
	BConfig.RecoverPanic = AppConfig.DefaultBool("RecoverPanic", BConfig.RecoverPanic)
	BConfig.RouterCaseSensitive = AppConfig.DefaultBool("RouterCaseSensitive", BConfig.RouterCaseSensitive)
A
astaxie 已提交
215
	BConfig.ServerName = AppConfig.DefaultString("ServerName", BConfig.ServerName)
A
astaxie 已提交
216 217 218 219 220
	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 已提交
221
	BConfig.Listen.HTTPAddr = AppConfig.String("HTTPAddr")
A
astaxie 已提交
222 223
	BConfig.Listen.HTTPPort = AppConfig.DefaultInt("HTTPPort", BConfig.Listen.HTTPPort)
	BConfig.Listen.ListenTCP4 = AppConfig.DefaultBool("ListenTCP4", BConfig.Listen.ListenTCP4)
A
astaxie 已提交
224 225
	BConfig.Listen.EnableHTTP = AppConfig.DefaultBool("EnableHTTP", BConfig.Listen.EnableHTTP)
	BConfig.Listen.EnableHTTPS = AppConfig.DefaultBool("EnableHTTPS", BConfig.Listen.EnableHTTPS)
A
astaxie 已提交
226
	BConfig.Listen.HTTPSAddr = AppConfig.DefaultString("HTTPSAddr", BConfig.Listen.HTTPSAddr)
A
astaxie 已提交
227
	BConfig.Listen.HTTPSPort = AppConfig.DefaultInt("HTTPSPort", BConfig.Listen.HTTPSPort)
A
astaxie 已提交
228 229 230 231 232
	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 已提交
233
	BConfig.Listen.EnableFcgi = AppConfig.DefaultBool("EnableFcgi", BConfig.Listen.EnableFcgi)
A
astaxie 已提交
234
	BConfig.Listen.EnableStdIo = AppConfig.DefaultBool("EnableStdIo", BConfig.Listen.EnableStdIo)
A
astaxie 已提交
235
	BConfig.Listen.ServerTimeOut = AppConfig.DefaultInt64("ServerTimeOut", BConfig.Listen.ServerTimeOut)
A
astaxie 已提交
236 237 238
	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 已提交
239
	BConfig.WebConfig.FlashName = AppConfig.DefaultString("FlashName", BConfig.WebConfig.FlashName)
J
JessonChan 已提交
240
	BConfig.WebConfig.FlashSeparator = AppConfig.DefaultString("FlashSeparator", BConfig.WebConfig.FlashSeparator)
A
astaxie 已提交
241
	BConfig.WebConfig.EnableDocs = AppConfig.DefaultBool("EnableDocs", BConfig.WebConfig.EnableDocs)
J
JessonChan 已提交
242
	BConfig.WebConfig.XSRFKey = AppConfig.DefaultString("XSRFKEY", BConfig.WebConfig.XSRFKey)
A
astaxie 已提交
243 244 245 246 247 248 249 250 251 252
	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 已提交
253 254
	BConfig.WebConfig.Session.SessionAutoSetCookie = AppConfig.DefaultBool("SessionAutoSetCookie", BConfig.WebConfig.Session.SessionAutoSetCookie)
	BConfig.WebConfig.Session.SessionDomain = AppConfig.DefaultString("SessionDomain", BConfig.WebConfig.Session.SessionDomain)
Y
youngsterxyf 已提交
255 256
	BConfig.Log.AccessLogs = AppConfig.DefaultBool("LogAccessLogs", BConfig.Log.AccessLogs)
	BConfig.Log.FileLineNum = AppConfig.DefaultBool("LogFileLineNum", BConfig.Log.FileLineNum)
A
astaxie 已提交
257

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

A
astaxie 已提交
272 273
	if sgz := AppConfig.String("StaticExtensionsToGzip"); sgz != "" {
		extensions := strings.Split(sgz, ",")
J
JessonChan 已提交
274
		fileExts := []string{}
J
JessonChan 已提交
275 276 277 278
		for _, ext := range extensions {
			ext = strings.TrimSpace(ext)
			if ext == "" {
				continue
F
Francois 已提交
279
			}
J
JessonChan 已提交
280 281 282
			if !strings.HasPrefix(ext, ".") {
				ext = "." + ext
			}
J
JessonChan 已提交
283 284 285
			fileExts = append(fileExts, ext)
		}
		if len(fileExts) > 0 {
A
astaxie 已提交
286
			BConfig.WebConfig.StaticExtensionsToGzip = fileExts
F
Francois 已提交
287
		}
A
astaxie 已提交
288
	}
Y
youngsterxyf 已提交
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310

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

	//init log
	BeeLogger.Close()
	for adaptor, config := range BConfig.Log.Outputs {
		err = BeeLogger.SetLogger(adaptor, config)
		if err != nil {
			fmt.Printf("%s with the config `%s` got err:%s\n", adaptor, config, err)
		}
	}
	SetLogFuncCall(BConfig.Log.FileLineNum)

A
astaxie 已提交
311
	return nil
312
}
A
astaxie 已提交
313

Y
youngsterxyf 已提交
314
// LoadAppConfig allow developer to apply a config file
315
func LoadAppConfig(adapterName, configPath string) error {
Y
youngsterxyf 已提交
316 317 318 319
	absConfigPath, err := filepath.Abs(configPath)
	if err != nil {
		return err
	}
Y
youngsterxyf 已提交
320 321

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

325
	if absConfigPath == appConfigPath {
Y
youngsterxyf 已提交
326 327 328
		return nil
	}

329 330
	appConfigPath = absConfigPath
	appConfigProvider = adapterName
Y
youngsterxyf 已提交
331

332
	return parseConfig(appConfigPath)
Y
youngsterxyf 已提交
333 334
}

A
astaxie 已提交
335 336 337 338
type beegoAppConfig struct {
	innerConfig config.Configer
}

339 340
func newAppConfig(appConfigProvider, appConfigPath string) (*beegoAppConfig, error) {
	ac, err := config.NewConfig(appConfigProvider, appConfigPath)
A
astaxie 已提交
341 342 343
	if err != nil {
		return nil, err
	}
F
fuxiaohei 已提交
344
	return &beegoAppConfig{ac}, nil
A
astaxie 已提交
345 346 347
}

func (b *beegoAppConfig) Set(key, val string) error {
F
fuxiaohei 已提交
348
	if err := b.innerConfig.Set(BConfig.RunMode+"::"+key, val); err != nil {
A
astaxie 已提交
349 350 351 352 353 354
		return err
	}
	return b.innerConfig.Set(key, val)
}

func (b *beegoAppConfig) String(key string) string {
F
fuxiaohei 已提交
355 356
	if v := b.innerConfig.String(BConfig.RunMode + "::" + key); v != "" {
		return v
A
astaxie 已提交
357
	}
F
fuxiaohei 已提交
358
	return b.innerConfig.String(key)
A
astaxie 已提交
359 360 361
}

func (b *beegoAppConfig) Strings(key string) []string {
F
fuxiaohei 已提交
362
	if v := b.innerConfig.Strings(BConfig.RunMode + "::" + key); v[0] != "" {
F
fud 已提交
363
		return v
A
astaxie 已提交
364
	}
F
fuxiaohei 已提交
365
	return b.innerConfig.Strings(key)
A
astaxie 已提交
366 367 368
}

func (b *beegoAppConfig) Int(key string) (int, error) {
F
fuxiaohei 已提交
369 370
	if v, err := b.innerConfig.Int(BConfig.RunMode + "::" + key); err == nil {
		return v, nil
A
astaxie 已提交
371
	}
F
fuxiaohei 已提交
372
	return b.innerConfig.Int(key)
A
astaxie 已提交
373 374 375
}

func (b *beegoAppConfig) Int64(key string) (int64, error) {
F
fuxiaohei 已提交
376 377
	if v, err := b.innerConfig.Int64(BConfig.RunMode + "::" + key); err == nil {
		return v, nil
A
astaxie 已提交
378
	}
F
fuxiaohei 已提交
379
	return b.innerConfig.Int64(key)
A
astaxie 已提交
380 381 382
}

func (b *beegoAppConfig) Bool(key string) (bool, error) {
F
fuxiaohei 已提交
383 384
	if v, err := b.innerConfig.Bool(BConfig.RunMode + "::" + key); err == nil {
		return v, nil
A
astaxie 已提交
385
	}
F
fuxiaohei 已提交
386
	return b.innerConfig.Bool(key)
A
astaxie 已提交
387 388 389
}

func (b *beegoAppConfig) Float(key string) (float64, error) {
F
fuxiaohei 已提交
390 391
	if v, err := b.innerConfig.Float(BConfig.RunMode + "::" + key); err == nil {
		return v, nil
A
astaxie 已提交
392
	}
F
fuxiaohei 已提交
393
	return b.innerConfig.Float(key)
A
astaxie 已提交
394 395 396
}

func (b *beegoAppConfig) DefaultString(key string, defaultval string) string {
F
fuxiaohei 已提交
397
	if v := b.String(key); v != "" {
A
astaxie 已提交
398 399 400 401 402 403
		return v
	}
	return defaultval
}

func (b *beegoAppConfig) DefaultStrings(key string, defaultval []string) []string {
F
fuxiaohei 已提交
404
	if v := b.Strings(key); len(v) != 0 {
A
astaxie 已提交
405 406 407 408 409 410
		return v
	}
	return defaultval
}

func (b *beegoAppConfig) DefaultInt(key string, defaultval int) int {
F
fuxiaohei 已提交
411
	if v, err := b.Int(key); err == nil {
A
astaxie 已提交
412 413 414 415 416 417
		return v
	}
	return defaultval
}

func (b *beegoAppConfig) DefaultInt64(key string, defaultval int64) int64 {
F
fuxiaohei 已提交
418
	if v, err := b.Int64(key); err == nil {
A
astaxie 已提交
419 420 421 422 423 424
		return v
	}
	return defaultval
}

func (b *beegoAppConfig) DefaultBool(key string, defaultval bool) bool {
F
fuxiaohei 已提交
425
	if v, err := b.Bool(key); err == nil {
A
astaxie 已提交
426 427 428 429 430 431
		return v
	}
	return defaultval
}

func (b *beegoAppConfig) DefaultFloat(key string, defaultval float64) float64 {
F
fuxiaohei 已提交
432
	if v, err := b.Float(key); err == nil {
A
astaxie 已提交
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
		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)
}