Compare commits

...

38 Commits

Author SHA1 Message Date
notzippy
97ec142262 Merge pull request #117 from tike/master
fix import path trimming during main.go generation
2018-02-04 16:32:57 -08:00
tike
dfc873bc15 fix import path trimming during main.go generation
The importPathFromPath function invoked during `revel build`
in callchain Build -> ProcessSource ->  importPathFromPath
assumes that the vendor folder is in the app's root directory
when trimming import paths for inclusion into autogenerated
templates.

Consequently vendor detection fails if the vendor folder
is located at another hiher layer in the directory tree
and /prefix/path/to/vendor/ is not stripped from the
import path, leading to inclusion of invalid importpaths,
resulting in compilation error and build abortion.

This fix makes the vendor folder detection more flexible,
allowing for the vendor folder to be present at any higher
level in the directory hirachy.
2018-02-01 15:25:13 +01:00
notzippy
cca02dd5ff Merge pull request #116 from notzippy/log-update
Added check to ignore functions which have no body (external functions)
2018-01-30 09:47:56 -08:00
NotZippy
91f43bf94c Added check to ignore functions which have no body (external functions)
Added missing sort package
2018-01-30 09:23:21 -08:00
notzippy
0583fe7d32 Merge pull request #108 from rokeller/develop
Generate same value of AppVersion regardless of where revel is run
2018-01-29 21:28:08 -08:00
notzippy
6ca1d73b61 Merge pull request #112 from nathantchan/stable_controllers
Sort controllers so that builds are reproducible.
2018-01-29 21:27:18 -08:00
notzippy
4c87861642 Merge pull request #114 from vin01/master
Adding referrer policy security header
2018-01-29 21:26:33 -08:00
notzippy
a2d7517ca0 Merge pull request #115 from runner-mei/master
add support to map as a argument in the controller action
2018-01-29 21:25:49 -08:00
meifakun
8efaff19ce map as a argument in the controller action 2018-01-15 16:07:46 +08:00
vin01
ac056d17af Adding referrer policy security header
It will set a default strict `Referrer-Policy ``strict-origin-when-cross-origin`` that controls what referrer information shall be included with requests.
More: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy, https://scotthelme.co.uk/a-new-security-header-referrer-policy/
It can prevent issues like: https://robots.thoughtbot.com/is-your-site-leaking-password-reset-links
2018-01-06 14:05:20 +05:30
Nathan Chan
fc904827cd Make sorting compatible with go >= 1.6 2017-12-11 09:55:26 -08:00
Nathan Chan
c240b05369 Sort controllers so that builds are reproducible.
Ordering of controllers in routes.go and main.go is unstable in
successive runs of revel build.  This change will assure that the
ordering is stable.
2017-12-08 11:37:28 -08:00
notzippy
29e594435c Merge pull request #104 from notzippy/log-update
Prerelease items
2017-10-31 08:12:16 -07:00
Roger Keller
a2acbe32bf Make sure AppVersion is set without the -dirty suffix for non-dirty work trees regardless of where revel is run from. 2017-10-28 21:20:28 +02:00
NotZippy
29c6237caf Removed the catch all route, and added comment about security issue 2017-10-22 09:31:18 -07:00
NotZippy
2d4ccf289c Set line number to use left parenthesis not right 2017-10-07 21:41:23 -07:00
notzippy
f38fb6a15d Merge pull request #103 from notzippy/log-update
Updated skeleton to added critical.
2017-10-07 21:41:05 -07:00
NotZippy
637ccbd250 Updated skeleton to added critical.
modified db.import to support multiple packages
2017-10-07 21:39:13 -07:00
notzippy
2da4734499 Merge pull request #101 from notzippy/log-update
Vendor changes
2017-09-25 09:10:40 -07:00
NotZippy
aa9e0f8600 Added code to make vendoring work 2017-09-25 07:36:48 -07:00
notzippy
db4054233b Merge pull request #99 from Acidic9/master
Remove abort with 'revel new' on empty directory
2017-09-24 13:17:32 -07:00
Ari Seyhun
3907c6575e Clean code 2017-09-23 14:20:09 +09:30
notzippy
27e9fab270 Merge pull request #100 from notzippy/log-update
Logging error added more compile warnings
2017-09-21 10:50:28 -07:00
NotZippy
17e7d40d31 Fixed missing debug context parameter name
Added check to see if specfication was not exported
Added warnings if expected types did not match specification
2017-09-20 17:49:34 -07:00
Ari Seyhun
54ce8d3699 Remove abort with 'revel new' on empty directory
If you use 'revel new ...' on an empty directory, revel will abort complaining the directory exists.

With this commit, it will no longer abort if the directory is empty.
2017-09-16 15:24:37 +09:30
notzippy
8ab98db556 Merge pull request #98 from notzippy/log-update
Updated command to use new logging
2017-09-14 17:16:59 -07:00
NotZippy
baf5e9f848 Added check to see if parameter was a local object, if so parse it 2017-09-14 17:15:22 -07:00
NotZippy
9d57681ae6 Updated command to use new logging 2017-09-02 09:10:21 -07:00
notzippy
3f136726db Merge pull request #97 from notzippy/listener-fix
Changed listener to be a pointer receiver
2017-08-25 15:55:14 -07:00
NotZippy
c0a515facf Changed listener to be a pointer receiver so setting the channel to nil actually persists 2017-08-24 21:48:49 -07:00
notzippy
01494f75fb Merge pull request #96 from notzippy/autorun
Added mutex lock on Refresh, removed check for app existence
2017-08-07 20:55:21 -07:00
NotZippy
e6b34786bb Added mutex lock on Refresh, removed check for app existence 2017-08-07 16:56:19 -07:00
notzippy
79b2afb5e5 Merge pull request #95 from notzippy/autorun
Made develop mode autorun on start
2017-08-03 20:00:26 -07:00
NotZippy
5fcde12193 Moved watcher inside harness
Modified proxy so application is launched on startup
2017-07-28 13:27:28 -07:00
notzippy
ad68773b9e Merge pull request #91 from notzippy/server-engine-2
Server Engine 2
2017-07-24 12:49:34 -07:00
NotZippy
e5255cd373 Updated as requested 2017-07-06 15:31:43 -07:00
NotZippy
3cf6d5094e Changed skeleton back to original 2017-06-07 09:45:09 -07:00
NotZippy
efcd02de37 Modified harness to bootstrap using the go engine. Skeleton app updated to use new request code 2017-06-07 09:45:09 -07:00
12 changed files with 291 additions and 208 deletions

View File

@@ -58,11 +58,11 @@ func NewAppCmd(binPath string, port int) AppCmd {
// Start the app server, and wait until it is ready to serve requests.
func (cmd AppCmd) Start() error {
listeningWriter := startupListeningWriter{os.Stdout, make(chan bool)}
listeningWriter := &startupListeningWriter{os.Stdout, make(chan bool)}
cmd.Stdout = listeningWriter
revel.TRACE.Println("Exec app:", cmd.Path, cmd.Args)
revel.RevelLog.Debug("Exec app:", "path", cmd.Path, "args", cmd.Args)
if err := cmd.Cmd.Start(); err != nil {
revel.ERROR.Fatalln("Error running:", err)
revel.RevelLog.Fatal("Error running:", "error", err)
}
select {
@@ -70,6 +70,7 @@ func (cmd AppCmd) Start() error {
return errors.New("revel/harness: app died")
case <-time.After(30 * time.Second):
revel.RevelLog.Debug("Killing revel server process did not respond after wait timeout", "processid", cmd.Process.Pid)
cmd.Kill()
return errors.New("revel/harness: app timed out")
@@ -83,19 +84,19 @@ func (cmd AppCmd) Start() error {
// Run the app server inline. Never returns.
func (cmd AppCmd) Run() {
revel.TRACE.Println("Exec app:", cmd.Path, cmd.Args)
revel.RevelLog.Debug("Exec app:", "path", cmd.Path, "args", cmd.Args)
if err := cmd.Cmd.Run(); err != nil {
revel.ERROR.Fatalln("Error running:", err)
revel.RevelLog.Fatal("Error running:", "error", err)
}
}
// Kill terminates the app server if it's running.
func (cmd AppCmd) Kill() {
if cmd.Cmd != nil && (cmd.ProcessState == nil || !cmd.ProcessState.Exited()) {
revel.TRACE.Println("Killing revel server pid", cmd.Process.Pid)
revel.RevelLog.Debug("Killing revel server pid", "pid", cmd.Process.Pid)
err := cmd.Process.Kill()
if err != nil {
revel.ERROR.Fatalln("Failed to kill revel server:", err)
revel.RevelLog.Fatal("Failed to kill revel server:", "error", err)
}
}
}
@@ -118,7 +119,7 @@ type startupListeningWriter struct {
notifyReady chan bool
}
func (w startupListeningWriter) Write(p []byte) (n int, err error) {
func (w *startupListeningWriter) Write(p []byte) (n int, err error) {
if w.notifyReady != nil && bytes.Contains(p, []byte("Listening")) {
w.notifyReady <- true
w.notifyReady = nil

152
harness/build.go Executable file → Normal file
View File

@@ -17,12 +17,19 @@ import (
"strings"
"text/template"
"time"
"sort"
"github.com/revel/revel"
)
var importErrorPattern = regexp.MustCompile("cannot find package \"([^\"]+)\"")
type ByString []*TypeInfo
func (c ByString) Len() int { return len(c) }
func (c ByString) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c ByString) Less(i, j int) bool { return c[i].String() < c[j].String() }
// Build the app:
// 1. Generate the the main.go file.
// 2. Run the appropriate "go build" command.
@@ -39,12 +46,16 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
// Add the db.import to the import paths.
if dbImportPath, found := revel.Config.String("db.import"); found {
sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, dbImportPath)
sourceInfo.InitImportPaths = append(sourceInfo.InitImportPaths, strings.Split(dbImportPath, ",")...)
}
// Sort controllers so that file generation is reproducible
controllers := sourceInfo.ControllerSpecs()
sort.Stable(ByString(controllers))
// Generate two source files.
templateArgs := map[string]interface{}{
"Controllers": sourceInfo.ControllerSpecs(),
"Controllers": controllers,
"ValidationKeys": sourceInfo.ValidationKeys,
"ImportPaths": calcImportAliases(sourceInfo),
"TestSuites": sourceInfo.TestSuites(),
@@ -59,12 +70,46 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
// It relies on the user having "go" installed.
goPath, err := exec.LookPath("go")
if err != nil {
revel.ERROR.Fatalf("Go executable not found in PATH.")
revel.RevelLog.Fatalf("Go executable not found in PATH.")
}
// Detect if deps tool should be used (is there a vendor folder ?)
useVendor := revel.DirExists(filepath.Join(revel.BasePath, "vendor"))
basePath := revel.BasePath
for !useVendor {
basePath = filepath.Dir(basePath)
found := false
// Check to see if we are still in the GOPATH
for _, path := range filepath.SplitList(build.Default.GOPATH) {
if strings.HasPrefix(basePath, path) {
found = true
break
}
}
if !found {
break
} else {
useVendor = revel.DirExists(filepath.Join(basePath, "vendor"))
}
}
var depPath string
if useVendor {
revel.RevelLog.Info("Vendor folder detected, scanning for deps in path")
depPath, err = exec.LookPath("dep")
if err != nil {
// Do not halt build unless a new package needs to be imported
revel.RevelLog.Warn("Build: `dep` executable not found in PATH, but vendor folder detected." +
"Packages can only be added automatically to the vendor folder using the `dep` tool. " +
"You can install the `dep` tool by doing a `go get -u github.com/golang/dep/cmd/dep`")
}
} else {
revel.RevelLog.Info("No vendor folder detected, not using dependency manager to import files")
}
pkg, err := build.Default.Import(revel.ImportPath, "", build.FindOnly)
if err != nil {
revel.ERROR.Fatalln("Failure importing", revel.ImportPath)
revel.RevelLog.Fatal("Failure importing", "path", revel.ImportPath)
}
// Binary path is a combination of $GOBIN/revel.d directory, app's import path and its name.
@@ -87,13 +132,6 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
versionLinkerFlags := fmt.Sprintf("-X %s/app.AppVersion=%s -X %s/app.BuildTime=%s",
revel.ImportPath, appVersion, revel.ImportPath, buildTime)
// TODO remove version check for versionLinkerFlags after Revel becomes Go min version to go1.5
goVersion, err := strconv.ParseFloat(runtime.Version()[2:5], 64)
// runtime.Version() may return commit hash, we assume it is above 1.5
if goVersion < 1.5 && err == nil {
versionLinkerFlags = fmt.Sprintf("-X %s/app.AppVersion \"%s\" -X %s/app.BuildTime \"%s\"",
revel.ImportPath, appVersion, revel.ImportPath, buildTime)
}
flags := []string{
"build",
"-i",
@@ -109,42 +147,58 @@ func Build(buildFlags ...string) (app *App, compileError *revel.Error) {
flags = append(flags, path.Join(revel.ImportPath, "app", "tmp"))
buildCmd := exec.Command(goPath, flags...)
revel.TRACE.Println("Exec:", buildCmd.Args)
revel.RevelLog.Debug("Exec:", "args", buildCmd.Args)
output, err := buildCmd.CombinedOutput()
// If the build succeeded, we're done.
if err == nil {
return NewApp(binName), nil
}
revel.ERROR.Println(string(output))
revel.RevelLog.Error(string(output))
// See if it was an import error that we can go get.
matches := importErrorPattern.FindStringSubmatch(string(output))
matches := importErrorPattern.FindAllStringSubmatch(string(output), -1)
if matches == nil {
return nil, newCompileError(output)
}
for _, match := range matches {
// Ensure we haven't already tried to go get it.
pkgName := match[1]
if _, alreadyTried := gotten[pkgName]; alreadyTried {
return nil, newCompileError(output)
}
gotten[pkgName] = struct{}{}
// Ensure we haven't already tried to go get it.
pkgName := matches[1]
if _, alreadyTried := gotten[pkgName]; alreadyTried {
return nil, newCompileError(output)
}
gotten[pkgName] = struct{}{}
// Execute "go get <pkg>"
getCmd := exec.Command(goPath, "get", pkgName)
revel.TRACE.Println("Exec:", getCmd.Args)
getOutput, err := getCmd.CombinedOutput()
if err != nil {
revel.ERROR.Println(string(getOutput))
return nil, newCompileError(output)
// Execute "go get <pkg>"
// Or dep `dep ensure -add <pkg>` if it is there
var getCmd *exec.Cmd
if useVendor {
if depPath == "" {
revel.RevelLog.Error("Build: Vendor folder found, but the `dep` tool was not found, " +
"if you use a different vendoring (package management) tool please add the following packages by hand, " +
"or install the `dep` tool into your gopath by doing a `go get -u github.com/golang/dep/cmd/dep`. " +
"For more information and usage of the tool please see http://github.com/golang/dep")
for _, pkg := range matches {
revel.RevelLog.Error("Missing package", "package", pkg[1])
}
}
getCmd = exec.Command(depPath, "ensure", "-add", pkgName)
} else {
getCmd = exec.Command(goPath, "get", pkgName)
}
revel.RevelLog.Debug("Exec:", "args", getCmd.Args)
getOutput, err := getCmd.CombinedOutput()
if err != nil {
revel.RevelLog.Error(string(getOutput))
return nil, newCompileError(output)
}
}
// Success getting the import, attempt to build again.
}
// TODO remove this unreachable code and document it
revel.ERROR.Fatalf("Not reachable")
revel.RevelLog.Fatalf("Not reachable")
return nil, nil
}
@@ -167,12 +221,12 @@ func getAppVersion() string {
if (err != nil && os.IsNotExist(err)) || !info.IsDir() {
return ""
}
gitCmd := exec.Command(gitPath, "--git-dir="+gitDir, "describe", "--always", "--dirty")
revel.TRACE.Println("Exec:", gitCmd.Args)
gitCmd := exec.Command(gitPath, "--git-dir="+gitDir, "--work-tree="+revel.BasePath, "describe", "--always", "--dirty")
revel.RevelLog.Debug("Exec:", "args", gitCmd.Args)
output, err := gitCmd.Output()
if err != nil {
revel.WARN.Println("Cannot determine git repository version:", err)
revel.RevelLog.Warn("Cannot determine git repository version:", "error", err)
return ""
}
@@ -189,12 +243,12 @@ func cleanSource(dirs ...string) {
}
func cleanDir(dir string) {
revel.INFO.Println("Cleaning dir " + dir)
revel.RevelLog.Info("Cleaning dir " + dir)
tmpPath := filepath.Join(revel.AppPath, dir)
f, err := os.Open(tmpPath)
if err != nil {
if !os.IsNotExist(err) {
revel.ERROR.Println("Failed to clean dir:", err)
revel.RevelLog.Error("Failed to clean dir:", "error", err)
}
} else {
defer func() {
@@ -204,20 +258,20 @@ func cleanDir(dir string) {
infos, err := f.Readdir(0)
if err != nil {
if !os.IsNotExist(err) {
revel.ERROR.Println("Failed to clean dir:", err)
revel.RevelLog.Error("Failed to clean dir:", "error", err)
}
} else {
for _, info := range infos {
path := filepath.Join(tmpPath, info.Name())
pathName := filepath.Join(tmpPath, info.Name())
if info.IsDir() {
err := os.RemoveAll(path)
err := os.RemoveAll(pathName)
if err != nil {
revel.ERROR.Println("Failed to remove dir:", err)
revel.RevelLog.Error("Failed to remove dir:", "error", err)
}
} else {
err := os.Remove(path)
err := os.Remove(pathName)
if err != nil {
revel.ERROR.Println("Failed to remove file:", err)
revel.RevelLog.Error("Failed to remove file:", "error", err)
}
}
}
@@ -237,20 +291,20 @@ func genSource(dir, filename, templateSource string, args map[string]interface{}
tmpPath := filepath.Join(revel.AppPath, dir)
err := os.Mkdir(tmpPath, 0777)
if err != nil && !os.IsExist(err) {
revel.ERROR.Fatalf("Failed to make '%v' directory: %v", dir, err)
revel.RevelLog.Fatalf("Failed to make '%v' directory: %v", dir, err)
}
// Create the file
file, err := os.Create(filepath.Join(tmpPath, filename))
if err != nil {
revel.ERROR.Fatalf("Failed to create file: %v", err)
revel.RevelLog.Fatalf("Failed to create file: %v", err)
}
defer func() {
_ = file.Close()
}()
if _, err = file.WriteString(sourceCode); err != nil {
revel.ERROR.Fatalf("Failed to write to file: %v", err)
revel.RevelLog.Fatalf("Failed to write to file: %v", err)
}
}
@@ -287,7 +341,7 @@ func calcImportAliases(src *SourceInfo) map[string]string {
}
func addAlias(aliases map[string]string, importPath, pkgName string) {
alias, ok := aliases[importPath]
alias, ok := aliases[importPath]
if ok {
return
}
@@ -298,7 +352,7 @@ func addAlias(aliases map[string]string, importPath, pkgName string) {
func makePackageAlias(aliases map[string]string, pkgName string) string {
i := 0
alias := pkgName
for containsValue(aliases, alias) || alias=="revel" {
for containsValue(aliases, alias) || alias == "revel" {
alias = fmt.Sprintf("%s%d", pkgName, i)
i++
}
@@ -323,7 +377,7 @@ func newCompileError(output []byte) *revel.Error {
errorMatch = regexp.MustCompile(`(?m)^(.*?)\:(\d+)\:\s(.*?)$`).FindSubmatch(output)
if errorMatch == nil {
revel.ERROR.Println("Failed to parse build errors:\n", string(output))
revel.RevelLog.Error("Failed to parse build errors", "error", string(output))
return &revel.Error{
SourceType: "Go code",
Title: "Go Compilation Error",
@@ -333,7 +387,7 @@ func newCompileError(output []byte) *revel.Error {
errorMatch = append(errorMatch, errorMatch[3])
revel.ERROR.Println("Build errors:\n", string(output))
revel.RevelLog.Error("Build errors", "errors", string(output))
}
// Read the source for the offending file.
@@ -360,7 +414,7 @@ func newCompileError(output []byte) *revel.Error {
fileStr, err := revel.ReadLines(absFilename)
if err != nil {
compileError.MetaError = absFilename + ": " + err.Error()
revel.ERROR.Println(compileError.MetaError)
revel.RevelLog.Error(compileError.MetaError)
return compileError
}
@@ -393,7 +447,7 @@ var (
func main() {
flag.Parse()
revel.Init(*runMode, *importPath, *srcPath)
revel.INFO.Println("Running revel server")
revel.AppLog.Info("Running revel server")
{{range $i, $c := .Controllers}}
revel.RegisterController((*{{index $.ImportPaths .ImportPath}}.{{.StructName}})(nil),
[]*revel.MethodType{

View File

@@ -29,10 +29,10 @@ import (
"sync/atomic"
"github.com/revel/revel"
"sync"
)
var (
watcher *revel.Watcher
doNotWatch = []string{"tmp", "views", "routes"}
lastRequestHadError int32
@@ -45,12 +45,16 @@ type Harness struct {
serverHost string
port int
proxy *httputil.ReverseProxy
watcher *revel.Watcher
mutex *sync.Mutex
}
func renderError(w http.ResponseWriter, r *http.Request, err error) {
req, resp := revel.NewRequest(r), revel.NewResponse(w)
c := revel.NewController(req, resp)
c.RenderError(err).Apply(req, resp)
func renderError(iw http.ResponseWriter, ir *http.Request, err error) {
context := revel.NewGoContext(nil)
context.Request.SetRequest(ir)
context.Response.SetResponse(iw)
c := revel.NewController(context)
c.RenderError(err).Apply(c.Request, c.Response)
}
// ServeHTTP handles all requests.
@@ -63,12 +67,17 @@ func (h *Harness) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Flush any change events and rebuild app if necessary.
// Render an error page if the rebuild / restart failed.
err := watcher.Notify()
err := h.watcher.Notify()
if err != nil {
// In a thread safe manner update the flag so that a request for
// /favicon.ico does not trigger a rebuild
atomic.CompareAndSwapInt32(&lastRequestHadError, 0, 1)
renderError(w, r, err)
return
}
// In a thread safe manner update the flag so that a request for
// /favicon.ico is allowed
atomic.CompareAndSwapInt32(&lastRequestHadError, 1, 0)
// Reverse proxy the request.
@@ -88,7 +97,7 @@ func NewHarness() *Harness {
revel.MainTemplateLoader = revel.NewTemplateLoader(
[]string{filepath.Join(revel.RevelPath, "templates")})
if err := revel.MainTemplateLoader.Refresh(); err != nil {
revel.ERROR.Println(err)
revel.RevelLog.Error("Template loader error", "error", err)
}
addr := revel.HTTPAddr
@@ -109,27 +118,32 @@ func NewHarness() *Harness {
serverURL, _ := url.ParseRequestURI(fmt.Sprintf(scheme+"://%s:%d", addr, port))
harness := &Harness{
serverHarness := &Harness{
port: port,
serverHost: serverURL.String()[len(scheme+"://"):],
proxy: httputil.NewSingleHostReverseProxy(serverURL),
mutex: &sync.Mutex{},
}
if revel.HTTPSsl {
harness.proxy.Transport = &http.Transport{
serverHarness.proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
}
return harness
return serverHarness
}
// Refresh method rebuilds the Revel application and run it on the given port.
func (h *Harness) Refresh() (err *revel.Error) {
// Allow only one thread to rebuild the process
h.mutex.Lock()
defer h.mutex.Unlock()
if h.app != nil {
h.app.Kill()
}
revel.TRACE.Println("Rebuild")
revel.RevelLog.Debug("Rebuild Called")
h.app, err = Build()
if err != nil {
return
@@ -153,7 +167,7 @@ func (h *Harness) WatchDir(info os.FileInfo) bool {
}
// WatchFile method returns true given filename HasSuffix of ".go"
// otheriwse false
// otheriwse false - implements revel.DiscerningListener
func (h *Harness) WatchFile(filename string) bool {
return strings.HasSuffix(filename, ".go")
}
@@ -167,12 +181,13 @@ func (h *Harness) Run() {
paths = append(paths, gopaths...)
}
paths = append(paths, revel.CodePaths...)
watcher = revel.NewWatcher()
watcher.Listen(h, paths...)
h.watcher = revel.NewWatcher()
h.watcher.Listen(h, paths...)
h.watcher.Notify()
go func() {
addr := fmt.Sprintf("%s:%d", revel.HTTPAddr, revel.HTTPPort)
revel.INFO.Printf("Listening on %s", addr)
revel.RevelLog.Infof("Listening on %s", addr)
var err error
if revel.HTTPSsl {
@@ -185,7 +200,7 @@ func (h *Harness) Run() {
err = http.ListenAndServe(addr, h)
}
if err != nil {
revel.ERROR.Fatalln("Failed to start reverse proxy:", err)
revel.RevelLog.Error("Failed to start reverse proxy:", "error", err)
}
}()
@@ -203,13 +218,13 @@ func (h *Harness) Run() {
func getFreePort() (port int) {
conn, err := net.Listen("tcp", ":0")
if err != nil {
revel.ERROR.Fatal(err)
revel.RevelLog.Fatal("Unable to fetch a freee port address", "error", err)
}
port = conn.Addr().(*net.TCPAddr).Port
err = conn.Close()
if err != nil {
revel.ERROR.Fatal(err)
revel.RevelLog.Fatal("Unable to close port", "error", err)
}
return port
}
@@ -231,7 +246,7 @@ func proxyWebsocket(w http.ResponseWriter, r *http.Request, host string) {
}
if err != nil {
http.Error(w, "Error contacting backend server.", 500)
revel.ERROR.Printf("Error dialing websocket backend %s: %v", host, err)
revel.RevelLog.Error("Error dialing websocket backend ", "host", host, "error", err)
return
}
hj, ok := w.(http.Hijacker)
@@ -241,21 +256,21 @@ func proxyWebsocket(w http.ResponseWriter, r *http.Request, host string) {
}
nc, _, err := hj.Hijack()
if err != nil {
revel.ERROR.Printf("Hijack error: %v", err)
revel.RevelLog.Error("Hijack error", "error", err)
return
}
defer func() {
if err = nc.Close(); err != nil {
revel.ERROR.Println(err)
revel.RevelLog.Error("Connection close error", "error", err)
}
if err = d.Close(); err != nil {
revel.ERROR.Println(err)
revel.RevelLog.Error("Dial close error", "error", err)
}
}()
err = r.Write(d)
if err != nil {
revel.ERROR.Printf("Error copying request to target: %v", err)
revel.RevelLog.Error("Error copying request to target", "error", err)
return
}

View File

@@ -13,12 +13,14 @@ import (
"go/parser"
"go/scanner"
"go/token"
"log"
"os"
"path/filepath"
"strings"
"unicode"
"github.com/revel/revel"
"log"
)
// SourceInfo is the top-level struct containing all extracted information
@@ -98,14 +100,14 @@ func ProcessSource(roots []string) (*SourceInfo, *revel.Error) {
for _, root := range roots {
rootImportPath := importPathFromPath(root)
if rootImportPath == "" {
revel.WARN.Println("Skipping code path", root)
revel.RevelLog.Warn("Skipping empty code path", "path", root)
continue
}
// Start walking the directory tree.
_ = revel.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Println("Error scanning app source:", err)
revel.RevelLog.Error("Error scanning app source:", "error", err)
return nil
}
@@ -149,7 +151,7 @@ func ProcessSource(roots []string) (*SourceInfo, *revel.Error) {
// This is exception, err alredy checked above. Here just a print
ast.Print(nil, err)
log.Fatalf("Failed to parse dir: %s", err)
revel.RevelLog.Fatal("Failed to parse dir", "error", err)
}
// Skip "main" packages.
@@ -160,9 +162,21 @@ func ProcessSource(roots []string) (*SourceInfo, *revel.Error) {
return nil
}
// Ignore packages that end with _test
for i := range pkgs {
if len(i) > 6 {
if string(i[len(i)-5:]) == "_test" {
delete(pkgs, i)
}
}
}
// There should be only one package in this directory.
if len(pkgs) > 1 {
log.Println("Most unexpected! Multiple packages in a single directory:", pkgs)
for i := range pkgs {
println("Found package ", i)
}
revel.RevelLog.Error("Most unexpected! Multiple packages in a single directory:", "packages", pkgs)
}
var pkg *ast.Package
@@ -187,7 +201,7 @@ func appendSourceInfo(srcInfo1, srcInfo2 *SourceInfo) *SourceInfo {
srcInfo1.InitImportPaths = append(srcInfo1.InitImportPaths, srcInfo2.InitImportPaths...)
for k, v := range srcInfo2.ValidationKeys {
if _, ok := srcInfo1.ValidationKeys[k]; ok {
log.Println("Key conflict when scanning validation calls:", k)
revel.RevelLog.Warn("Key conflict when scanning validation calls:", "key", k)
continue
}
srcInfo1.ValidationKeys[k] = v
@@ -209,8 +223,8 @@ func processPackage(fset *token.FileSet, pkgImportPath, pkgPath string, pkg *ast
)
// For each source file in the package...
log.Println("Exaiming files in path", pkgPath)
for _, file := range pkg.Files {
// Imports maps the package key to the full import path.
// e.g. import "sample/app/models" => "models": "sample/app/models"
imports := map[string]string{}
@@ -227,8 +241,8 @@ func processPackage(fset *token.FileSet, pkgImportPath, pkgPath string, pkg *ast
structSpecs = appendStruct(structSpecs, pkgImportPath, pkg, decl, imports, fset)
}
// If this is a func...
if funcDecl, ok := decl.(*ast.FuncDecl); ok {
// If this is a func... (ignore nil for external (non-Go) function)
if funcDecl, ok := decl.(*ast.FuncDecl); ok && funcDecl.Body != nil {
// Scan it for validation calls
lineKeys := getValidationKeys(fset, funcDecl, imports)
if len(lineKeys) > 0 {
@@ -305,7 +319,7 @@ func addImports(imports map[string]string, decl ast.Decl, srcDir string) {
// We expect this to happen for apps using reverse routing (since we
// have not yet generated the routes). Don't log that.
if !strings.HasSuffix(fullPath, "/app/routes") {
revel.TRACE.Println("Could not find import:", fullPath)
revel.RevelLog.Debug("Could not find import:", "path", fullPath)
}
continue
}
@@ -324,6 +338,7 @@ func appendStruct(specs []*TypeInfo, pkgImportPath string, pkg *ast.Package, dec
if !found {
return specs
}
structType := spec.Type.(*ast.StructType)
// At this point we know it's a type declaration for a struct.
@@ -383,7 +398,7 @@ func appendStruct(specs []*TypeInfo, pkgImportPath string, pkg *ast.Package, dec
} else {
var ok bool
if importPath, ok = imports[pkgName]; !ok {
log.Print("Failed to find import path for ", pkgName, ".", typeName)
revel.RevelLog.Error("Failed to find import path for ", "package", pkgName, "type", typeName)
continue
}
}
@@ -442,13 +457,16 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat
var importPath string
typeExpr := NewTypeExpr(pkgName, field.Type)
if !typeExpr.Valid {
log.Printf("Didn't understand argument '%s' of action %s. Ignoring.\n", name, getFuncName(funcDecl))
revel.RevelLog.Warnf("Didn't understand argument '%s' of action %s. Ignoring.", name, getFuncName(funcDecl))
return // We didn't understand one of the args. Ignore this action.
}
if typeExpr.PkgName != "" {
// Local object
if typeExpr.PkgName == pkgName {
importPath = pkgImportPath
} else if typeExpr.PkgName != "" {
var ok bool
if importPath, ok = imports[typeExpr.PkgName]; !ok {
log.Println("Failed to find import for arg of type:", typeExpr.TypeName(""))
revel.RevelLog.Errorf("Failed to find import for arg of type: %s , %s", typeExpr.PkgName, typeExpr.TypeName(""))
}
}
method.Args = append(method.Args, &MethodArg{
@@ -482,7 +500,7 @@ func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPat
}
// Add this call's args to the renderArgs.
pos := fset.Position(callExpr.Rparen)
pos := fset.Position(callExpr.Lparen)
methodCall := &methodCall{
Line: pos.Line,
Names: []string{},
@@ -634,7 +652,7 @@ func getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec,
}
if len(genDecl.Specs) == 0 {
revel.WARN.Printf("Surprising: %s:%d Decl contains no specifications", fset.Position(decl.Pos()).Filename, fset.Position(decl.Pos()).Line)
revel.RevelLog.Warnf("Surprising: %s:%d Decl contains no specifications", fset.Position(decl.Pos()).Filename, fset.Position(decl.Pos()).Line)
return
}
@@ -647,7 +665,7 @@ func getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec,
// TypesThatEmbed returns all types that (directly or indirectly) embed the
// target type, which must be a fully qualified type name,
// e.g. "github.com/revel/revel.Controller"
func (s *SourceInfo) TypesThatEmbed(targetType string) (filtered []*TypeInfo) {
func (s *SourceInfo) TypesThatEmbed(targetType, packageFilter string) (filtered []*TypeInfo) {
// Do a search in the "embedded type graph", starting with the target type.
var (
nodeQueue = []string{targetType}
@@ -679,6 +697,37 @@ func (s *SourceInfo) TypesThatEmbed(targetType string) (filtered []*TypeInfo) {
}
}
}
// Strip out any specifications that contain a lower case
for exit := false; !exit; exit = true {
for i, filteredItem := range filtered {
if unicode.IsLower([]rune(filteredItem.StructName)[0]) {
revel.RevelLog.Debug("Skipping adding spec for unexported type",
"type", filteredItem.StructName,
"package", filteredItem.ImportPath)
filtered = append(filtered[:i], filtered[i+1:]...)
exit = false
break
}
}
}
// Check for any missed types that where from expected packages
for _, spec := range s.StructSpecs {
if spec.PackageName == packageFilter {
found := false
for _, filteredItem := range filtered {
if filteredItem.StructName == spec.StructName {
found = true
break
}
}
if !found {
revel.RevelLog.Warn("Type found in package: "+packageFilter+
", but did not embed from: "+filepath.Base(targetType),
"name", spec.StructName, "path", spec.ImportPath)
}
}
}
return
}
@@ -686,7 +735,7 @@ func (s *SourceInfo) TypesThatEmbed(targetType string) (filtered []*TypeInfo) {
// `revel.Controller`
func (s *SourceInfo) ControllerSpecs() []*TypeInfo {
if s.controllerSpecs == nil {
s.controllerSpecs = s.TypesThatEmbed(revel.RevelImportPath + ".Controller")
s.controllerSpecs = s.TypesThatEmbed(revel.RevelImportPath+".Controller", "controllers")
}
return s.controllerSpecs
}
@@ -695,7 +744,7 @@ func (s *SourceInfo) ControllerSpecs() []*TypeInfo {
// `testing.TestSuite`
func (s *SourceInfo) TestSuites() []*TypeInfo {
if s.testSuites == nil {
s.testSuites = s.TypesThatEmbed(revel.RevelImportPath + "/testing.TestSuite")
s.testSuites = s.TypesThatEmbed(revel.RevelImportPath+"/testing.TestSuite", "testsuite")
}
return s.testSuites
}
@@ -735,11 +784,18 @@ func NewTypeExpr(pkgName string, expr ast.Expr) TypeExpr {
case *ast.ArrayType:
e := NewTypeExpr(pkgName, t.Elt)
return TypeExpr{"[]" + e.Expr, e.PkgName, e.pkgIndex + 2, e.Valid}
case *ast.MapType:
if identKey, ok := t.Key.(*ast.Ident); ok && IsBuiltinType(identKey.Name) {
e := NewTypeExpr(pkgName, t.Value)
return TypeExpr{"map[" + identKey.Name + "]" + e.Expr, e.PkgName, e.pkgIndex + len("map["+identKey.Name+"]"), e.Valid}
}
revel.RevelLog.Error("Failed to generate name for field. Make sure the field name is valid.")
case *ast.Ellipsis:
e := NewTypeExpr(pkgName, t.Elt)
return TypeExpr{"[]" + e.Expr, e.PkgName, e.pkgIndex + 2, e.Valid}
default:
log.Println("Failed to generate name for field. Make sure the field name is valid.")
revel.RevelLog.Error("Failed to generate name for field. Make sure the field name is valid.", "package", pkgName, "expresion",expr)
}
return TypeExpr{Valid: false}
}
@@ -774,9 +830,8 @@ func IsBuiltinType(name string) bool {
}
func importPathFromPath(root string) string {
vendoringPath := revel.BasePath + "/vendor/"
if strings.HasPrefix(root, vendoringPath) {
return filepath.ToSlash(root[len(vendoringPath):])
if vendorIdx := strings.Index(root, "/vendor/"); vendorIdx != -1 {
return filepath.ToSlash(root[vendorIdx+8:])
}
for _, gopath := range filepath.SplitList(build.Default.GOPATH) {
srcPath := filepath.Join(gopath, "src")
@@ -787,10 +842,10 @@ func importPathFromPath(root string) string {
srcPath := filepath.Join(build.Default.GOROOT, "src", "pkg")
if strings.HasPrefix(root, srcPath) {
revel.WARN.Println("Code path should be in GOPATH, but is in GOROOT:", root)
revel.RevelLog.Warn("Code path should be in GOPATH, but is in GOROOT:", "path", root)
return filepath.ToSlash(root[len(srcPath)+1:])
}
revel.ERROR.Println("Unexpected! Code path is not in GOPATH:", root)
revel.RevelLog.Error("Unexpected! Code path is not in GOPATH:", "path", root)
return ""
}

View File

@@ -8,8 +8,6 @@ import (
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"log"
"reflect"
"strings"
"testing"
@@ -96,18 +94,20 @@ func TestGetValidationKeys(t *testing.T) {
}
var TypeExprs = map[string]TypeExpr{
"int": {"int", "", 0, true},
"*int": {"*int", "", 1, true},
"[]int": {"[]int", "", 2, true},
"...int": {"[]int", "", 2, true},
"[]*int": {"[]*int", "", 3, true},
"...*int": {"[]*int", "", 3, true},
"MyType": {"MyType", "pkg", 0, true},
"*MyType": {"*MyType", "pkg", 1, true},
"[]MyType": {"[]MyType", "pkg", 2, true},
"...MyType": {"[]MyType", "pkg", 2, true},
"[]*MyType": {"[]*MyType", "pkg", 3, true},
"...*MyType": {"[]*MyType", "pkg", 3, true},
"int": {"int", "", 0, true},
"*int": {"*int", "", 1, true},
"[]int": {"[]int", "", 2, true},
"...int": {"[]int", "", 2, true},
"[]*int": {"[]*int", "", 3, true},
"...*int": {"[]*int", "", 3, true},
"MyType": {"MyType", "pkg", 0, true},
"*MyType": {"*MyType", "pkg", 1, true},
"[]MyType": {"[]MyType", "pkg", 2, true},
"...MyType": {"[]MyType", "pkg", 2, true},
"[]*MyType": {"[]*MyType", "pkg", 3, true},
"...*MyType": {"[]*MyType", "pkg", 3, true},
"map[int]MyType": {"map[int]MyType", "pkg", 8, true},
"map[int]*MyType": {"map[int]*MyType", "pkg", 9, true},
}
func TestTypeExpr(t *testing.T) {
@@ -183,7 +183,7 @@ NEXT_TEST:
func BenchmarkProcessBookingSource(b *testing.B) {
revel.Init("", "github.com/revel/examples/booking", "")
revel.TRACE = log.New(ioutil.Discard, "", 0)
revel.GetRootLogHandler().Disable()
b.ResetTimer()
for i := 0; i < b.N; i++ {

View File

@@ -60,11 +60,11 @@ func buildApp(args []string) {
}
if err := os.RemoveAll(destPath); err != nil && !os.IsNotExist(err) {
revel.ERROR.Fatalln(err)
revel.RevelLog.Fatal("Remove all error","error", err)
}
if err := os.MkdirAll(destPath, 0777); err != nil {
revel.ERROR.Fatalln(err)
revel.RevelLog.Fatal("makedir error","error",err)
}
app, reverr := harness.Build()
@@ -101,7 +101,7 @@ func buildApp(args []string) {
}
modulePath, err := revel.ResolveImportPath(moduleImportPath)
if err != nil {
revel.ERROR.Fatalln("Failed to load module %s: %s", key[len("module."):], err)
revel.RevelLog.Fatalf("Failed to load module %s: %s", key[len("module."):], err)
}
modulePaths[moduleImportPath] = modulePath
}

View File

@@ -8,7 +8,6 @@ import (
"bytes"
"fmt"
"go/build"
"log"
"math/rand"
"os"
"os/exec"
@@ -67,8 +66,6 @@ func newApp(args []string) {
errorf("Too many arguments provided.\nRun 'revel help new' for usage.\n")
}
revel.ERROR.SetFlags(log.LstdFlags)
// checking and setting go paths
initGoPaths()
@@ -129,7 +126,7 @@ func initGoPaths() {
}
if len(srcRoot) == 0 {
revel.ERROR.Fatalln("Abort: could not create a Revel application outside of GOPATH.")
revel.RevelLog.Fatal("Abort: could not create a Revel application outside of GOPATH.")
}
// set go src path
@@ -148,8 +145,10 @@ func setApplicationPath(args []string) {
importPath)
}
appPath = filepath.Join(srcRoot, filepath.FromSlash(importPath))
_, err = build.Import(importPath, "", build.FindOnly)
if err == nil {
if err == nil && !empty(appPath) {
errorf("Abort: Import path %s already exists.\n", importPath)
}
@@ -158,7 +157,6 @@ func setApplicationPath(args []string) {
errorf("Abort: Could not find Revel source code: %s\n", err)
}
appPath = filepath.Join(srcRoot, filepath.FromSlash(importPath))
appName = filepath.Base(appPath)
basePath = filepath.ToSlash(filepath.Dir(importPath))

View File

@@ -53,7 +53,7 @@ func packageApp(args []string) {
// Remove the archive if it already exists.
destFile := filepath.Base(revel.BasePath) + ".tar.gz"
if err := os.Remove(destFile); err != nil && !os.IsNotExist(err) {
revel.ERROR.Fatal(err)
revel.RevelLog.Fatal("Unable to remove target file","error",err,"file",destFile)
}
// Collect stuff in a temp directory.

View File

@@ -51,7 +51,7 @@ func parseRunArgs(args []string) *RunArgs {
}
switch len(args) {
case 3:
// Possibile combinations
// Possible combinations
// revel run [import-path] [run-mode] [port]
port, err := strconv.Atoi(args[2])
if err != nil {
@@ -61,7 +61,7 @@ func parseRunArgs(args []string) *RunArgs {
inputArgs.Mode = args[1]
inputArgs.Port = port
case 2:
// Possibile combinations
// Possible combinations
// 1. revel run [import-path] [run-mode]
// 2. revel run [import-path] [port]
// 3. revel run [run-mode] [port]
@@ -85,11 +85,16 @@ func parseRunArgs(args []string) *RunArgs {
inputArgs.Port = port
}
case 1:
// Possibile combinations
// Possible combinations
// 1. revel run [import-path]
// 2. revel run [port]
// 3. revel run [run-mode]
if _, err := build.Import(args[0], "", build.FindOnly); err == nil {
_, err := build.Import(args[0], "", build.FindOnly)
if err != nil {
revel.RevelLog.Warn("Unable to run using an import path, assuming import path is working directory %s %s", "Argument", args[0], "error", err.Error())
}
println("Trying to build with", args[0], err)
if err == nil {
// 1st arg is the import path
inputArgs.ImportPath = args[0]
} else if port, err := strconv.Atoi(args[0]); err == nil {
@@ -116,18 +121,18 @@ func runApp(args []string) {
runArgs.Port = revel.HTTPPort
}
revel.INFO.Printf("Running %s (%s) in %s mode\n", revel.AppName, revel.ImportPath, runArgs.Mode)
revel.TRACE.Println("Base path:", revel.BasePath)
revel.RevelLog.Infof("Running %s (%s) in %s mode\n", revel.AppName, revel.ImportPath, runArgs.Mode)
revel.RevelLog.Debug("Base path:", "path", revel.BasePath)
// If the app is run in "watched" mode, use the harness to run it.
if revel.Config.BoolDefault("watch", true) && revel.Config.BoolDefault("watch.code", true) {
revel.TRACE.Println("Running in watched mode.")
revel.RevelLog.Debug("Running in watched mode.")
revel.HTTPPort = runArgs.Port
harness.NewHarness().Run() // Never returns.
}
// Else, just build and run the app.
revel.TRACE.Println("Running in live build mode.")
revel.RevelLog.Debug("Running in live build mode.")
app, err := harness.Build()
if err != nil {
errorf("Failed to build app: %s", err)

View File

@@ -29,8 +29,7 @@ func init() {
revel.ActionInvoker, // Invoke the action.
}
// register startup functions with OnAppStart
// Register startup functions with OnAppStart
// revel.DevMode and revel.RunMode only work inside of OnAppStart. See Example Startup Script
// ( order dependent )
// revel.OnAppStart(ExampleStartupScript)
@@ -39,13 +38,13 @@ func init() {
}
// HeaderFilter adds common security headers
// TODO turn this into revel.HeaderFilter
// should probably also have a filter for CSRF
// not sure if it can go in the same filter or not
// There is a full implementation of a CSRF filter in
// https://github.com/revel/modules/tree/master/csrf
var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) {
c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN")
c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block")
c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff")
c.Response.Out.Header().Add("Referrer-Policy", "strict-origin-when-cross-origin")
fc[0](c, fc[1:]) // Execute the next filter stage.
}

View File

@@ -84,15 +84,6 @@ format.datetime = 2006-01-02 15:04
results.chunked = false
# Prefixes for each log message line.
# User can override these prefix values within any section
# For e.g: [dev], [prod], etc
log.trace.prefix = "TRACE "
log.info.prefix = "INFO "
log.warn.prefix = "WARN "
log.error.prefix = "ERROR "
# The default language of this application.
i18n.default_language = en
@@ -104,7 +95,7 @@ i18n.default_language = en
# Module to serve static content such as CSS, JavaScript and Media files
# Allows Routes like this:
# `Static.ServeModule("modulename","public")`
module.static=github.com/revel/modules/static
module.static = github.com/revel/modules/static
@@ -179,37 +170,14 @@ module.testrunner = github.com/revel/modules/testrunner
# Log to Os's standard error output. Default value.
# "relative/path/to/log"
# Log to file.
log.trace.output = off
log.info.output = stderr
log.warn.output = stderr
log.error.output = stderr
# Revel log flags. Possible flags defined by the Go `log` package. Go log is
# "Bits OR'ed together to control what's printed
# See:
# https://golang.org/pkg/log/#pkg-constants
# Values:
# "0"
# Just log the message, turn off the flags.
# "3"
# log.LstdFlags (log.Ldate|log.Ltime)
# "19"
# log.Ldate|log.Ltime|log.Lshortfile
# "23"
# log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile
log.trace.flags = 19
log.info.flags = 19
log.warn.flags = 19
log.error.flags = 19
log.all.filter.module.app = stdout # Log all loggers for the application to the stdout
log.error.nfilter.module.app = stderr # Everything else that logs an error to stderr
log.crit.output = stderr # Everything that logs something as critical goes to this
# Revel request access log
# Access log line format:
# RequestStartTime ClientIP ResponseStatus RequestLatency HTTPMethod URLPath
# Sample format:
# 2016/05/25 17:46:37.112 127.0.0.1 200 270.157µs GET /
log.request.output = stderr
# INFO 21:53:55 static server-engine.go:169: Request Stats ip=127.0.0.1 path=/public/vendors/datatables.net-buttons/js/buttons.html5.min.js method=GET start=2017/08/31 21:53:55 status=200 duration_seconds=0.0002583 section=requestlog
log.request.output = stdout
@@ -229,30 +197,11 @@ watch = false
module.testrunner =
log.trace.output = off
log.info.output = off
log.warn.output = log/%(app.name)s.log
log.error.output = log/%(app.name)s.log
log.warn.output = log/%(app.name)-warn.json # Log all warn messages to file
log.error.output = log/%(app.name)-error.json # Log all errors to file
log.crit.output = log/%(app.name)-critical.json # Log all critical to file
# Revel log flags. Possible flags defined by the Go `log` package,
# please refer https://golang.org/pkg/log/#pkg-constants
# Go log is "Bits or'ed together to control what's printed"
# Examples:
# 0 => just log the message, turn off the flags
# 3 => log.LstdFlags (log.Ldate|log.Ltime)
# 19 => log.Ldate|log.Ltime|log.Lshortfile
# 23 => log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile
log.trace.flags = 3
log.info.flags = 3
log.warn.flags = 3
log.error.flags = 3
# Revel request access log
# Access log line format:
# RequestStartTime ClientIP ResponseStatus RequestLatency HTTPMethod URLPath
# Sample format:
# 2016/05/25 17:46:37.112 127.0.0.1 200 270.157µs GET /
# Revel request access log (json format)
# Example:
# log.request.output = %(app.name)s-request.log
log.request.output = off
# log.request.output = %(app.name)s-request.json
log.request.output = log/%(app.name)s-requests.json

View File

@@ -15,5 +15,12 @@ GET /favicon.ico 404
# Map static resources from the /app/public folder to the /public path
GET /public/*filepath Static.Serve("public")
# Catch all
* /:controller/:action :controller.:action
# Catch all, this will route any request into the controller path
#
# **** WARNING ****
# Enabling this exposes any controller and function to the web.
# ** This is a serious security issue if used online **
#
# For rapid development uncomment the following to add new controller.action endpoints
# without having to add them to the routes table.
# * /:controller/:action :controller.:action