Beego/config.go

498 lines
13 KiB
Go
Raw Permalink Normal View History

2014-08-18 08:41:43 +00:00
// Copyright 2014 beego Author. All Rights Reserved.
2014-07-03 15:40:21 +00:00
//
2014-08-18 08:41:43 +00:00
// 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
2014-07-03 15:40:21 +00:00
//
2014-08-18 08:41:43 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2014-07-03 15:40:21 +00:00
//
2014-08-18 08:41:43 +00:00
// 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 (
2016-02-02 09:12:47 +00:00
"fmt"
"os"
"path/filepath"
2016-04-13 09:51:54 +00:00
"reflect"
2016-09-15 04:16:24 +00:00
"runtime"
"strings"
2013-12-03 11:26:51 +00:00
"github.com/astaxie/beego/config"
2016-09-15 04:16:24 +00:00
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/logs"
2013-12-03 11:26:51 +00:00
"github.com/astaxie/beego/session"
"github.com/astaxie/beego/utils"
)
2016-01-17 16:22:11 +00:00
// Config is the main struct for BConfig
2016-01-17 16:18:21 +00:00
type Config struct {
2015-12-09 15:35:04 +00:00
AppName string //Application name
RunMode string //Running Mode: dev | prod
RouterCaseSensitive bool
2015-12-09 15:35:04 +00:00
ServerName string
RecoverPanic bool
2016-09-15 04:16:24 +00:00
RecoverFunc func(*context.Context)
2015-12-09 15:35:04 +00:00
CopyRequestBody bool
EnableGzip bool
MaxMemory int64
EnableErrorsShow bool
EnableErrorsRender bool
2015-12-09 15:35:04 +00:00
Listen Listen
WebConfig WebConfig
Log LogConfig
2014-10-01 14:10:33 +00:00
}
2016-01-17 16:18:21 +00:00
// Listen holds for http and https related config
2015-12-09 15:35:04 +00:00
type Listen struct {
2017-11-15 14:42:30 +00:00
Graceful bool // Graceful means use graceful module to start the server
ServerTimeOut int64
ListenTCP4 bool
EnableHTTP bool
HTTPAddr string
HTTPPort int
EnableHTTPS bool
EnableMutualHTTPS bool
HTTPSAddr string
HTTPSPort int
HTTPSCertFile string
HTTPSKeyFile string
TrustCaFile string
EnableAdmin bool
AdminAddr string
AdminPort int
EnableFcgi bool
EnableStdIo bool // EnableStdIo works with EnableFcgi Use FCGI via standard I/O
2014-10-01 14:10:33 +00:00
}
2016-01-17 16:18:21 +00:00
// WebConfig holds web related config
2015-12-09 15:35:04 +00:00
type WebConfig struct {
AutoRender bool
EnableDocs bool
FlashName string
2016-01-15 06:07:37 +00:00
FlashSeparator string
2015-12-09 15:35:04 +00:00
DirectoryIndex bool
StaticDir map[string]string
StaticExtensionsToGzip []string
TemplateLeft string
TemplateRight string
ViewsPath string
EnableXSRF bool
2016-01-15 06:07:37 +00:00
XSRFKey string
2015-12-09 15:35:04 +00:00
XSRFExpire int
Session SessionConfig
2014-10-01 14:10:33 +00:00
}
2016-01-17 16:18:21 +00:00
// SessionConfig holds session related config
2015-12-09 15:35:04 +00:00
type SessionConfig struct {
2016-10-11 16:02:56 +00:00
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
2014-10-01 14:10:33 +00:00
}
2016-01-17 16:18:21 +00:00
// LogConfig holds Log related config
2015-12-09 15:35:04 +00:00
type LogConfig struct {
2017-11-19 03:07:57 +00:00
AccessLogs bool
AccessLogsFormat string //access log format: JSON_FORMAT, APACHE_FORMAT or empty string
FileLineNum bool
Outputs map[string]string // Store Adaptor : config
2014-10-01 14:10:33 +00:00
}
2015-12-09 15:35:04 +00:00
var (
// BConfig is the default config for Application
2016-01-17 16:18:21 +00:00
BConfig *Config
2015-12-09 15:35:04 +00:00
// AppConfig is the instance of Config, store the config information from file
AppConfig *beegoAppConfig
2016-01-23 16:18:16 +00:00
// AppPath is the absolute path to the app
AppPath string
2015-12-09 15:35:04 +00:00
// GlobalSessions is the instance for the session manager
GlobalSessions *session.Manager
2016-01-26 16:10:21 +00:00
// appConfigPath is the path to the config files
appConfigPath string
// appConfigProvider is the provider for the config, default is ini
appConfigProvider = "ini"
2015-12-09 15:35:04 +00:00
)
2014-10-01 14:10:33 +00:00
2015-12-09 15:35:04 +00:00
func init() {
2016-04-14 03:51:00 +00:00
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)
}
2017-10-31 11:19:14 +00:00
var filename = "app.conf"
if os.Getenv("BEEGO_MODE") != "" {
filename = os.Getenv("BEEGO_MODE") + ".app.conf"
}
2017-10-30 05:54:36 +00:00
appConfigPath = filepath.Join(workPath, "conf", filename)
2016-04-14 03:51:00 +00:00
if !utils.FileExists(appConfigPath) {
2017-10-30 05:54:36 +00:00
appConfigPath = filepath.Join(AppPath, "conf", filename)
2016-04-14 03:51:00 +00:00
if !utils.FileExists(appConfigPath) {
AppConfig = &beegoAppConfig{innerConfig: config.NewFakeConfig()}
return
}
}
if err = parseConfig(appConfigPath); err != nil {
panic(err)
}
}
2016-01-27 04:13:26 +00:00
2016-09-15 04:16:24 +00:00
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 {
2016-09-15 04:16:24 +00:00
showErr(err, ctx, stack)
}
}
}
2016-04-14 03:51:00 +00:00
func newBConfig() *Config {
return &Config{
2015-12-09 15:35:04 +00:00
AppName: "beego",
RunMode: DEV,
2015-12-09 15:35:04 +00:00
RouterCaseSensitive: true,
ServerName: "beegoServer:" + VERSION,
RecoverPanic: true,
2016-09-15 04:16:24 +00:00
RecoverFunc: recoverPanic,
2015-12-09 15:35:04 +00:00
CopyRequestBody: false,
EnableGzip: false,
MaxMemory: 1 << 26, //64MB
EnableErrorsShow: true,
EnableErrorsRender: true,
2015-12-09 15:35:04 +00:00
Listen: Listen{
Graceful: false,
ServerTimeOut: 0,
ListenTCP4: false,
2016-01-12 13:55:02 +00:00
EnableHTTP: true,
2015-12-09 15:35:04 +00:00
HTTPAddr: "",
HTTPPort: 8080,
2016-01-12 13:55:02 +00:00
EnableHTTPS: false,
2015-12-09 15:35:04 +00:00
HTTPSAddr: "",
HTTPSPort: 10443,
HTTPSCertFile: "",
HTTPSKeyFile: "",
2016-01-12 13:55:02 +00:00
EnableAdmin: false,
2015-12-09 15:35:04 +00:00
AdminAddr: "",
AdminPort: 8088,
EnableFcgi: false,
EnableStdIo: false,
},
WebConfig: WebConfig{
AutoRender: true,
EnableDocs: false,
FlashName: "BEEGO_FLASH",
2016-01-15 06:07:37 +00:00
FlashSeparator: "BEEGOFLASH",
2015-12-09 15:35:04 +00:00
DirectoryIndex: false,
StaticDir: map[string]string{"/static": "static"},
StaticExtensionsToGzip: []string{".css", ".js"},
TemplateLeft: "{{",
TemplateRight: "}}",
ViewsPath: "views",
EnableXSRF: false,
2016-01-15 06:07:37 +00:00
XSRFKey: "beegoxsrf",
2015-12-09 15:35:04 +00:00
XSRFExpire: 0,
Session: SessionConfig{
2016-10-11 16:02:56 +00:00
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
2015-12-09 15:35:04 +00:00
},
},
Log: LogConfig{
2017-11-19 03:07:57 +00:00
AccessLogs: false,
AccessLogsFormat: "APACHE_FORMAT",
FileLineNum: true,
Outputs: map[string]string{"console": ""},
2015-12-09 15:35:04 +00:00
},
2015-04-05 15:21:13 +00:00
}
2016-01-26 16:10:21 +00:00
}
2015-12-09 15:35:04 +00:00
// now only support ini, next will support json.
2016-01-26 16:10:21 +00:00
func parseConfig(appConfigPath string) (err error) {
AppConfig, err = newAppConfig(appConfigProvider, appConfigPath)
2014-10-24 11:03:27 +00:00
if err != nil {
return err
}
2016-04-14 03:51:00 +00:00
return assignConfig(AppConfig)
}
func assignConfig(ac config.Configer) error {
2017-02-27 01:41:15 +00:00
for _, i := range []interface{}{BConfig, &BConfig.Listen, &BConfig.WebConfig, &BConfig.Log, &BConfig.WebConfig.Session} {
2017-02-26 14:20:11 +00:00
assignSingleConfig(i, ac)
}
2016-02-02 08:52:53 +00:00
// set the run mode first
2015-12-17 12:05:00 +00:00
if envRunMode := os.Getenv("BEEGO_RUNMODE"); envRunMode != "" {
2015-12-09 15:35:04 +00:00
BConfig.RunMode = envRunMode
2016-04-14 03:51:00 +00:00
} else if runMode := ac.String("RunMode"); runMode != "" {
2016-02-02 08:52:53 +00:00
BConfig.RunMode = runMode
2014-10-01 14:10:33 +00:00
}
2016-04-14 03:51:00 +00:00
if sd := ac.String("StaticDir"); sd != "" {
BConfig.WebConfig.StaticDir = map[string]string{}
2014-10-01 14:10:33 +00:00
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]
2014-10-01 14:10:33 +00:00
} else {
BConfig.WebConfig.StaticDir["/"+strings.Trim(url2fsmap[0], "/")] = url2fsmap[0]
}
}
2014-10-01 14:10:33 +00:00
}
2016-04-14 03:51:00 +00:00
if sgz := ac.String("StaticExtensionsToGzip"); sgz != "" {
2014-10-01 14:10:33 +00:00
extensions := strings.Split(sgz, ",")
2015-09-22 05:27:35 +00:00
fileExts := []string{}
2015-09-22 03:59:48 +00:00
for _, ext := range extensions {
ext = strings.TrimSpace(ext)
if ext == "" {
continue
2013-12-14 18:34:27 +00:00
}
2015-09-22 03:59:48 +00:00
if !strings.HasPrefix(ext, ".") {
ext = "." + ext
}
2015-09-22 05:27:35 +00:00
fileExts = append(fileExts, ext)
}
if len(fileExts) > 0 {
2015-12-09 15:35:04 +00:00
BConfig.WebConfig.StaticExtensionsToGzip = fileExts
2013-12-14 18:34:27 +00:00
}
2014-10-01 14:10:33 +00:00
}
2016-01-26 16:10:21 +00:00
2016-04-14 03:51:00 +00:00
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)
2016-01-26 16:10:21 +00:00
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()
2016-01-26 16:10:21 +00:00
for adaptor, config := range BConfig.Log.Outputs {
2016-04-14 03:51:00 +00:00
err := logs.SetLogger(adaptor, config)
2016-01-26 16:10:21 +00:00
if err != nil {
2016-04-27 14:17:53 +00:00
fmt.Fprintln(os.Stderr, fmt.Sprintf("%s with the config %q got err:%s", adaptor, config, err.Error()))
2016-01-26 16:10:21 +00:00
}
}
logs.SetLogFuncCall(BConfig.Log.FileLineNum)
2016-01-26 16:10:21 +00:00
2014-10-01 14:10:33 +00:00
return nil
}
2015-12-09 15:35:04 +00:00
2016-04-14 03:51:00 +00:00
func assignSingleConfig(p interface{}, ac config.Configer) {
2016-04-13 09:51:54 +00:00
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:
2017-03-17 17:45:30 +00:00
pf.SetInt(ac.DefaultInt64(name, pf.Int()))
2016-04-13 09:51:54 +00:00
case reflect.Bool:
pf.SetBool(ac.DefaultBool(name, pf.Bool()))
case reflect.Struct:
default:
2016-04-14 03:51:00 +00:00
//do nothing here
2016-04-13 09:51:54 +00:00
}
}
}
2016-01-26 16:10:21 +00:00
// LoadAppConfig allow developer to apply a config file
func LoadAppConfig(adapterName, configPath string) error {
2016-01-26 16:10:21 +00:00
absConfigPath, err := filepath.Abs(configPath)
if err != nil {
return err
}
2016-01-26 16:17:56 +00:00
if !utils.FileExists(absConfigPath) {
2016-01-29 05:11:11 +00:00
return fmt.Errorf("the target config file: %s don't exist", configPath)
2016-01-26 16:17:56 +00:00
}
appConfigPath = absConfigPath
appConfigProvider = adapterName
2016-01-26 16:10:21 +00:00
return parseConfig(appConfigPath)
2016-01-26 16:10:21 +00:00
}
2015-12-09 15:35:04 +00:00
type beegoAppConfig struct {
innerConfig config.Configer
}
func newAppConfig(appConfigProvider, appConfigPath string) (*beegoAppConfig, error) {
ac, err := config.NewConfig(appConfigProvider, appConfigPath)
2015-12-09 15:35:04 +00:00
if err != nil {
return nil, err
}
2015-12-17 12:05:00 +00:00
return &beegoAppConfig{ac}, nil
2015-12-09 15:35:04 +00:00
}
func (b *beegoAppConfig) Set(key, val string) error {
2015-12-17 12:05:00 +00:00
if err := b.innerConfig.Set(BConfig.RunMode+"::"+key, val); err != nil {
2015-12-09 15:35:04 +00:00
return err
}
return b.innerConfig.Set(key, val)
}
func (b *beegoAppConfig) String(key string) string {
2015-12-17 12:05:00 +00:00
if v := b.innerConfig.String(BConfig.RunMode + "::" + key); v != "" {
return v
2015-12-09 15:35:04 +00:00
}
2015-12-17 12:05:00 +00:00
return b.innerConfig.String(key)
2015-12-09 15:35:04 +00:00
}
func (b *beegoAppConfig) Strings(key string) []string {
2016-03-21 01:32:41 +00:00
if v := b.innerConfig.Strings(BConfig.RunMode + "::" + key); len(v) > 0 {
2015-12-21 08:05:26 +00:00
return v
2015-12-09 15:35:04 +00:00
}
2015-12-17 12:05:00 +00:00
return b.innerConfig.Strings(key)
2015-12-09 15:35:04 +00:00
}
func (b *beegoAppConfig) Int(key string) (int, error) {
2015-12-17 12:05:00 +00:00
if v, err := b.innerConfig.Int(BConfig.RunMode + "::" + key); err == nil {
return v, nil
2015-12-09 15:35:04 +00:00
}
2015-12-17 12:05:00 +00:00
return b.innerConfig.Int(key)
2015-12-09 15:35:04 +00:00
}
func (b *beegoAppConfig) Int64(key string) (int64, error) {
2015-12-17 12:05:00 +00:00
if v, err := b.innerConfig.Int64(BConfig.RunMode + "::" + key); err == nil {
return v, nil
2015-12-09 15:35:04 +00:00
}
2015-12-17 12:05:00 +00:00
return b.innerConfig.Int64(key)
2015-12-09 15:35:04 +00:00
}
func (b *beegoAppConfig) Bool(key string) (bool, error) {
2015-12-17 12:05:00 +00:00
if v, err := b.innerConfig.Bool(BConfig.RunMode + "::" + key); err == nil {
return v, nil
2015-12-09 15:35:04 +00:00
}
2015-12-17 12:05:00 +00:00
return b.innerConfig.Bool(key)
2015-12-09 15:35:04 +00:00
}
func (b *beegoAppConfig) Float(key string) (float64, error) {
2015-12-17 12:05:00 +00:00
if v, err := b.innerConfig.Float(BConfig.RunMode + "::" + key); err == nil {
return v, nil
2015-12-09 15:35:04 +00:00
}
2015-12-17 12:05:00 +00:00
return b.innerConfig.Float(key)
2015-12-09 15:35:04 +00:00
}
2016-02-02 08:52:53 +00:00
func (b *beegoAppConfig) DefaultString(key string, defaultVal string) string {
2015-12-17 12:05:00 +00:00
if v := b.String(key); v != "" {
2015-12-09 15:35:04 +00:00
return v
}
2016-02-02 08:52:53 +00:00
return defaultVal
2015-12-09 15:35:04 +00:00
}
2016-02-02 08:52:53 +00:00
func (b *beegoAppConfig) DefaultStrings(key string, defaultVal []string) []string {
2015-12-17 12:05:00 +00:00
if v := b.Strings(key); len(v) != 0 {
2015-12-09 15:35:04 +00:00
return v
}
2016-02-02 08:52:53 +00:00
return defaultVal
2015-12-09 15:35:04 +00:00
}
2016-02-02 08:52:53 +00:00
func (b *beegoAppConfig) DefaultInt(key string, defaultVal int) int {
2015-12-17 12:05:00 +00:00
if v, err := b.Int(key); err == nil {
2015-12-09 15:35:04 +00:00
return v
}
2016-02-02 08:52:53 +00:00
return defaultVal
2015-12-09 15:35:04 +00:00
}
2016-02-02 08:52:53 +00:00
func (b *beegoAppConfig) DefaultInt64(key string, defaultVal int64) int64 {
2015-12-17 12:05:00 +00:00
if v, err := b.Int64(key); err == nil {
2015-12-09 15:35:04 +00:00
return v
}
2016-02-02 08:52:53 +00:00
return defaultVal
2015-12-09 15:35:04 +00:00
}
2016-02-02 08:52:53 +00:00
func (b *beegoAppConfig) DefaultBool(key string, defaultVal bool) bool {
2015-12-17 12:05:00 +00:00
if v, err := b.Bool(key); err == nil {
2015-12-09 15:35:04 +00:00
return v
}
2016-02-02 08:52:53 +00:00
return defaultVal
2015-12-09 15:35:04 +00:00
}
2016-02-02 08:52:53 +00:00
func (b *beegoAppConfig) DefaultFloat(key string, defaultVal float64) float64 {
2015-12-17 12:05:00 +00:00
if v, err := b.Float(key); err == nil {
2015-12-09 15:35:04 +00:00
return v
}
2016-02-02 08:52:53 +00:00
return defaultVal
2015-12-09 15:35:04 +00:00
}
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)
}