1 // Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
2 // Revel Framework source code and usage is governed by a MIT style
3 // license that can be found in the LICENSE file.
15 "github.com/revel/config"
16 "github.com/revel/revel/logger"
17 "github.com/revel/revel/model"
21 // RevelImportPath Revel framework import path
22 RevelImportPath = "github.com/revel/revel"
26 TEST_MODE_FLAG = "testModeFlag"
27 SPECIAL_USE_FLAG = "specialUseFlag"
32 RevelConfig *model.RevelContainer
33 AppName string // e.g. "sample"
34 AppRoot string // e.g. "/app1"
35 BasePath string // e.g. "$GOPATH/src/corp/sample"
36 AppPath string // e.g. "$GOPATH/src/corp/sample/app"
37 ViewsPath string // e.g. "$GOPATH/src/corp/sample/app/views"
38 ImportPath string // e.g. "corp/sample"
39 SourcePath string // e.g. "$GOPATH/src"
41 Config *config.Context
42 RunMode string // Application-defined (by default, "dev" or "prod")
43 DevMode bool // if true, RunMode is a development mode.
45 // Revel installation details
46 RevelPath string // e.g. "$GOPATH/src/github.com/revel/revel"
48 // Where to look for templates
49 // Ordered by priority. (Earlier paths take precedence over later paths.)
50 CodePaths []string // Code base directories, for modules and app
51 TemplatePaths []string // Template path directories manually added
53 // ConfPaths where to look for configurations
55 // 1. framework (revel/conf/*)
56 // 2. application (conf/*)
57 // 3. user supplied configs (...) - User configs can override/add any from above
62 // Alert: This is how the app is configured, which may be different from
63 // the current process reality. For example, if the app is configured for
64 // port 9000, HTTPPort will always be 9000, even though in dev mode it is
65 // run on a random port and proxied.
66 HTTPPort int // e.g. 9000
67 HTTPAddr string // e.g. "", "127.0.0.1"
68 HTTPSsl bool // e.g. true if using ssl
69 HTTPSslCert string // e.g. "/path/to/cert.pem"
70 HTTPSslKey string // e.g. "/path/to/key.pem"
72 // All cookies dropped by the framework begin with this prefix.
79 // Revel request access log, not exposed from package.
80 // However output settings can be controlled from app.conf
82 // True when revel engine has been initialized (Init has returned)
86 secretKey []byte // Key used to sign cookies. An empty key disables signing.
87 packaged bool // If true, this is running from a pre-built package.
88 initEventList = []EventHandler{} // Event handler list for receiving events
91 // Init initializes Revel -- it provides paths for getting around the app.
94 // mode - the run mode, which determines which app.conf settings are used.
95 // importPath - the Go import path of the application.
96 // srcPath - the path to the source directory, containing Revel and the app.
97 // If not specified (""), then a functioning Go installation is required.
98 func Init(inputmode, importPath, srcPath string) {
99 RevelConfig = &model.RevelContainer{}
100 // Ignore trailing slashes.
101 ImportPath = strings.TrimRight(importPath, "/")
104 RunMode = updateLog(inputmode)
106 // If the SourcePath is not specified, find it using build.Import.
107 var revelSourcePath string // may be different from the app source path
108 if SourcePath == "" {
109 revelSourcePath, SourcePath = findSrcPaths(importPath)
111 // If the SourcePath was specified, assume both Revel and the app are within it.
112 SourcePath = filepath.Clean(SourcePath)
113 revelSourcePath = SourcePath
117 RevelPath = filepath.Join(revelSourcePath, filepath.FromSlash(RevelImportPath))
118 BasePath = filepath.Join(SourcePath, filepath.FromSlash(importPath))
119 AppPath = filepath.Join(BasePath, "app")
120 ViewsPath = filepath.Join(AppPath, "views")
122 CodePaths = []string{AppPath}
124 if ConfPaths == nil {
125 ConfPaths = []string{}
129 // 1. framework (revel/conf/*)
130 // 2. application (conf/*)
131 // 3. user supplied configs (...) - User configs can override/add any from above
134 filepath.Join(RevelPath, "conf"),
135 filepath.Join(BasePath, "conf"),
139 TemplatePaths = []string{
141 filepath.Join(RevelPath, "templates"),
146 Config, err = config.LoadContext("app.conf", ConfPaths)
147 if err != nil || Config == nil {
148 RevelLog.Fatal("Failed to load app.conf:", "error", err)
151 // After application config is loaded update the logger
154 // Configure properties from app.conf
155 DevMode = Config.BoolDefault("mode.dev", false)
156 HTTPPort = Config.IntDefault("http.port", 9000)
157 HTTPAddr = Config.StringDefault("http.addr", "")
158 HTTPSsl = Config.BoolDefault("http.ssl", false)
159 HTTPSslCert = Config.StringDefault("http.sslcert", "")
160 HTTPSslKey = Config.StringDefault("http.sslkey", "")
162 if HTTPSslCert == "" {
163 RevelLog.Fatal("No http.sslcert provided.")
165 if HTTPSslKey == "" {
166 RevelLog.Fatal("No http.sslkey provided.")
170 AppName = Config.StringDefault("app.name", "(not set)")
171 AppRoot = Config.StringDefault("app.root", "")
172 CookiePrefix = Config.StringDefault("cookie.prefix", "REVEL")
173 CookieDomain = Config.StringDefault("cookie.domain", "")
174 CookieSecure = Config.BoolDefault("cookie.secure", HTTPSsl)
175 if secretStr := Config.StringDefault("app.secret", ""); secretStr != "" {
176 SetSecretKey([]byte(secretStr))
179 RaiseEvent(REVEL_BEFORE_MODULES_LOADED, nil)
181 RaiseEvent(REVEL_AFTER_MODULES_LOADED, nil)
184 RevelLog.Info("Initialized Revel", "Version", Version, "BuildDate", BuildDate, "MinimumGoVersion", MinimumGoVersion)
187 // The input mode can be as simple as "prod" or it can be a JSON string like
188 // {"mode":"%s","testModeFlag":true}
189 // When this function is called it returns the true "inputmode" extracted from the parameter
190 // and it sets the log context appropriately
191 func updateLog(inputmode string) (returnMode string) {
193 returnMode = config.DefaultSection
196 returnMode = inputmode
199 // Check to see if the mode is a json object
200 modemap := map[string]interface{}{}
202 var testModeFlag, specialUseFlag bool
203 if err := json.Unmarshal([]byte(inputmode), &modemap); err == nil {
204 returnMode = modemap["mode"].(string)
205 if testmode, found := modemap[TEST_MODE_FLAG]; found {
206 testModeFlag, _ = testmode.(bool)
208 if specialUse, found := modemap[SPECIAL_USE_FLAG]; found {
209 specialUseFlag, _ = specialUse.(bool)
213 var newContext *config.Context
214 // If the Config is nil, set the logger to minimal log messages by adding the option
216 newContext = config.NewContext()
217 newContext.SetOption(TEST_MODE_FLAG, fmt.Sprint(true))
219 // Ensure that the selected runmode appears in app.conf.
220 // If empty string is passed as the mode, treat it as "DEFAULT"
221 if !Config.HasSection(returnMode) {
222 log.Fatalln("app.conf: No mode found:", returnMode)
224 Config.SetSection(returnMode)
228 // Only set the testmode flag if it doesnt exist
229 if _, found := newContext.Bool(TEST_MODE_FLAG); !found {
230 newContext.SetOption(TEST_MODE_FLAG, fmt.Sprint(testModeFlag))
232 if _, found := newContext.Bool(SPECIAL_USE_FLAG); !found {
233 newContext.SetOption(SPECIAL_USE_FLAG, fmt.Sprint(specialUseFlag))
236 appHandle := logger.InitializeFromConfig(BasePath, newContext)
238 // Set all the log handlers
239 setAppLog(AppLog, appHandle)
244 // Set the secret key
245 func SetSecretKey(newKey []byte) error {
250 // ResolveImportPath returns the filesystem path for the given import path.
251 // Returns an error if the import path could not be found.
252 func ResolveImportPath(importPath string) (string, error) {
254 return filepath.Join(SourcePath, importPath), nil
257 modPkg, err := build.Import(importPath, RevelPath, build.FindOnly)
261 return modPkg.Dir, nil
264 // CheckInit method checks `revel.Initialized` if not initialized it panics
267 RevelLog.Panic("CheckInit: Revel has not been initialized!")
271 // findSrcPaths uses the "go/build" package to find the source root for Revel
273 func findSrcPaths(importPath string) (revelSourcePath, appSourcePath string) {
275 gopaths = filepath.SplitList(build.Default.GOPATH)
276 goroot = build.Default.GOROOT
279 if len(gopaths) == 0 {
280 RevelLog.Fatal("GOPATH environment variable is not set. " +
281 "Please refer to http://golang.org/doc/code.html to configure your Go environment.")
284 if ContainsString(gopaths, goroot) {
285 RevelLog.Fatalf("GOPATH (%s) must not include your GOROOT (%s). "+
286 "Please refer to http://golang.org/doc/code.html to configure your Go environment.",
290 appPkg, err := build.Import(importPath, "", build.FindOnly)
292 RevelLog.Panic("Failed to import "+importPath+" with error:", "error", err)
295 revelPkg, err := build.Import(RevelImportPath, appPkg.Dir, build.FindOnly)
297 RevelLog.Fatal("Failed to find Revel with error:", "error", err)
300 return revelPkg.Dir[:len(revelPkg.Dir)-len(RevelImportPath)], appPkg.SrcRoot