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  }