github.com/segakazzz/buffalo@v0.16.22-0.20210119082501-1f52048d3feb/options.go (about) 1 package buffalo 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "strings" 8 9 "github.com/fatih/color" 10 "github.com/gobuffalo/buffalo/worker" 11 "github.com/gobuffalo/envy" 12 "github.com/gobuffalo/logger" 13 "github.com/gobuffalo/pop/v5" 14 "github.com/gobuffalo/pop/v5/logging" 15 "github.com/gorilla/sessions" 16 "github.com/markbates/oncer" 17 "github.com/segakazzz/buffalo/internal/defaults" 18 ) 19 20 // Options are used to configure and define how your application should run. 21 type Options struct { 22 Name string `json:"name"` 23 // Addr is the bind address provided to http.Server. Default is "127.0.0.1:3000" 24 // Can be set using ENV vars "ADDR" and "PORT". 25 Addr string `json:"addr"` 26 // Host that this application will be available at. Default is "http://127.0.0.1:[$PORT|3000]". 27 Host string `json:"host"` 28 29 // Env is the "environment" in which the App is running. Default is "development". 30 Env string `json:"env"` 31 32 // LogLevel defaults to "debug". Deprecated use LogLvl instead 33 LogLevel string `json:"log_level"` 34 // LogLevl defaults to logger.DebugLvl. 35 LogLvl logger.Level `json:"log_lvl"` 36 // Logger to be used with the application. A default one is provided. 37 Logger Logger `json:"-"` 38 39 // MethodOverride allows for changing of the request method type. See the default 40 // implementation at buffalo.MethodOverride 41 MethodOverride http.HandlerFunc `json:"-"` 42 43 // SessionStore is the `github.com/gorilla/sessions` store used to back 44 // the session. It defaults to use a cookie store and the ENV variable 45 // `SESSION_SECRET`. 46 SessionStore sessions.Store `json:"-"` 47 // SessionName is the name of the session cookie that is set. This defaults 48 // to "_buffalo_session". 49 SessionName string `json:"session_name"` 50 51 // Worker implements the Worker interface and can process tasks in the background. 52 // Default is "github.com/gobuffalo/worker.Simple. 53 Worker worker.Worker `json:"-"` 54 // WorkerOff tells App.Start() whether to start the Worker process or not. Default is "false". 55 WorkerOff bool `json:"worker_off"` 56 57 // PreHandlers are http.Handlers that are called between the http.Server 58 // and the buffalo Application. 59 PreHandlers []http.Handler `json:"-"` 60 // PreWare takes an http.Handler and returns and http.Handler 61 // and acts as a pseudo-middleware between the http.Server and 62 // a Buffalo application. 63 PreWares []PreWare `json:"-"` 64 65 // CompressFiles enables gzip compression of static files served by ServeFiles using 66 // gorilla's CompressHandler (https://godoc.org/github.com/gorilla/handlers#CompressHandler). 67 // Default is "false". 68 CompressFiles bool `json:"compress_files"` 69 70 Prefix string `json:"prefix"` 71 Context context.Context `json:"-"` 72 73 cancel context.CancelFunc 74 } 75 76 // PreWare takes an http.Handler and returns and http.Handler 77 // and acts as a pseudo-middleware between the http.Server and 78 // a Buffalo application. 79 type PreWare func(http.Handler) http.Handler 80 81 // NewOptions returns a new Options instance with sensible defaults 82 func NewOptions() Options { 83 return optionsWithDefaults(Options{}) 84 } 85 86 func optionsWithDefaults(opts Options) Options { 87 opts.Env = defaults.String(opts.Env, envy.Get("GO_ENV", "development")) 88 opts.Name = defaults.String(opts.Name, "/") 89 addr := "0.0.0.0" 90 if opts.Env == "development" { 91 addr = "127.0.0.1" 92 } 93 envAddr := envy.Get("ADDR", addr) 94 95 if strings.HasPrefix(envAddr, "unix:") { 96 // UNIX domain socket doesn't have a port 97 opts.Addr = envAddr 98 } else { 99 // TCP case 100 opts.Addr = defaults.String(opts.Addr, fmt.Sprintf("%s:%s", envAddr, envy.Get("PORT", "3000"))) 101 } 102 103 if opts.PreWares == nil { 104 opts.PreWares = []PreWare{} 105 } 106 if opts.PreHandlers == nil { 107 opts.PreHandlers = []http.Handler{} 108 } 109 110 if opts.Context == nil { 111 opts.Context = context.Background() 112 } 113 opts.Context, opts.cancel = context.WithCancel(opts.Context) 114 115 if opts.Logger == nil { 116 if lvl, err := envy.MustGet("LOG_LEVEL"); err == nil { 117 opts.LogLvl, err = logger.ParseLevel(lvl) 118 if err != nil { 119 opts.LogLvl = logger.DebugLevel 120 } 121 } 122 123 if len(opts.LogLevel) > 0 { 124 var err error 125 oncer.Deprecate(0, "github.com/gobuffalo/buffalo#Options.LogLevel", "Use github.com/gobuffalo/buffalo#Options.LogLvl instead.") 126 opts.LogLvl, err = logger.ParseLevel(opts.LogLevel) 127 if err != nil { 128 opts.LogLvl = logger.DebugLevel 129 } 130 } 131 if opts.LogLvl == 0 { 132 opts.LogLvl = logger.DebugLevel 133 } 134 135 opts.Logger = logger.New(opts.LogLvl) 136 } 137 138 pop.SetLogger(func(level logging.Level, s string, args ...interface{}) { 139 if !pop.Debug { 140 return 141 } 142 143 l := opts.Logger 144 if len(args) > 0 { 145 for i, a := range args { 146 l = l.WithField(fmt.Sprintf("$%d", i+1), a) 147 } 148 } 149 150 if pop.Color { 151 s = color.YellowString(s) 152 } 153 154 l.Debug(s) 155 }) 156 157 if opts.SessionStore == nil { 158 secret := envy.Get("SESSION_SECRET", "") 159 160 if secret == "" && (opts.Env == "development" || opts.Env == "test") { 161 secret = "buffalo-secret" 162 } 163 164 // In production a SESSION_SECRET must be set! 165 if secret == "" { 166 opts.Logger.Warn("Unless you set SESSION_SECRET env variable, your session storage is not protected!") 167 } 168 169 cookieStore := sessions.NewCookieStore([]byte(secret)) 170 171 //Cookie secure attributes, see: https://www.owasp.org/index.php/Testing_for_cookies_attributes_(OTG-SESS-002) 172 cookieStore.Options.HttpOnly = true 173 if opts.Env == "production" { 174 cookieStore.Options.Secure = true 175 } 176 177 opts.SessionStore = cookieStore 178 } 179 if opts.Worker == nil { 180 w := worker.NewSimpleWithContext(opts.Context) 181 w.Logger = opts.Logger 182 opts.Worker = w 183 } 184 opts.SessionName = defaults.String(opts.SessionName, "_buffalo_session") 185 opts.Host = defaults.String(opts.Host, envy.Get("HOST", fmt.Sprintf("http://127.0.0.1:%s", envy.Get("PORT", "3000")))) 186 return opts 187 }