Beego/config.go

511 lines
14 KiB
Go
Raw 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
2018-07-20 16:53:57 +00:00
AutoTLS bool
Domains []string
TLSCacheDir string
2017-11-15 14:42:30 +00:00
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.
2018-02-20 02:39:29 +00:00
SessionEnableSidInHTTPHeader bool // enable store/get the sessionId into/from http headers
2016-10-11 16:02:56 +00:00
SessionNameInHTTPHeader string
2018-02-20 02:39:29 +00:00
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
EnableStaticLogs bool //log static files requests default: false
2017-11-19 03:07:57 +00:00
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"
2018-02-20 02:39:29 +00:00
if os.Getenv("BEEGO_RUNMODE") != "" {
filename = os.Getenv("BEEGO_RUNMODE") + ".app.conf"
2017-10-31 11:19:14 +00:00
}
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)
}
2018-04-29 12:12:32 +00:00
if ctx.Output.Status != 0 {
ctx.ResponseWriter.WriteHeader(ctx.Output.Status)
} else {
ctx.ResponseWriter.WriteHeader(500)
}
2016-09-15 04:16:24 +00:00
}
}
2016-04-14 03:51:00 +00:00
func newBConfig() *Config {
return &Config{
2015-12-09 15:35:04 +00:00
AppName: "beego",
RunMode: PROD,
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,
2018-07-20 16:53:57 +00:00
AutoTLS: false,
Domains: []string{},
TLSCacheDir: ".",
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: "",
2018-02-20 02:39:29 +00:00
SessionEnableSidInHTTPHeader: false, // enable store/get the sessionId into/from http headers
2016-10-11 16:02:56 +00:00
SessionNameInHTTPHeader: "Beegosessionid",
2018-02-20 02:39:29 +00:00
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,
EnableStaticLogs: false,
2017-11-19 03:07:57 +00:00
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)
}