Browse Source

Macaron rewrite

Torkel Ödegaard 11 years ago
parent
commit
201e1d3e6d
9 changed files with 253 additions and 24 deletions
  1. 1 0
      .bra.toml
  2. 25 1
      conf/grafana.ini
  3. BIN
      grafana-pro
  4. 65 15
      pkg/cmd/web.go
  5. 58 0
      pkg/middleware/logger.go
  6. 52 0
      pkg/middleware/middleware.go
  7. 12 0
      pkg/routes/index.go
  8. 0 7
      pkg/routes/routes.go
  9. 40 1
      pkg/setting/setting.go

+ 1 - 0
.bra.toml

@@ -4,6 +4,7 @@ watch_all = true
 watch_dirs = [
 	"$WORKDIR/pkg",
 	"$WORKDIR/views",
+	"$WORKDIR/conf",
 ]
 watch_exts = [".go", ".ini"]
 build_delay = 1500

+ 25 - 1
conf/grafana.ini

@@ -8,7 +8,31 @@ root_url = %(protocol)s://%(domain)s:%(http_port)s/
 http_addr =
 http_port = 3000
 ssh_port = 22
-route_log = true
+router_logging = false
+
+[session]
+; Either "memory", "file", default is "memory"
+provider = file
+; Provider config options
+; memory: not have any config yet
+; file: session file path, e.g. `data/sessions`
+; redis: config like redis server addr, poolSize, password, e.g. `127.0.0.1:6379,100,gogs`
+; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
+provider_config = data/sessions
+; Session cookie name
+cookie_name = grafana_pro_sess
+; If you use session in https only, default is false
+cookie_secure = false
+; Enable set cookie, default is true
+enable_set_cookie = true
+; Session GC time interval, default is 86400
+gc_time_interval = 86400
+; Session life time, default is 86400
+session_life_time = 86400
+; session id hash func, Either "sha1", "sha256" or "md5" default is sha1
+session_id_hashfunc = sha1
+; Session hash key, default is use random string
+session_id_hashkey =
 
 [log]
 root_path =

BIN
grafana-pro


+ 65 - 15
pkg/cmd/web.go

@@ -1,12 +1,19 @@
+// Copyright 2014 Unknwon
+// Copyright 2014 Torkel Ödegaard
+
 package cmd
 
 import (
-	"time"
+	"fmt"
+	"net/http"
+	"path"
 
+	"github.com/Unknwon/macaron"
 	"github.com/codegangsta/cli"
-	"github.com/siddontang/go-log/log"
-	"github.com/torkelo/grafana-pro/pkg/configuration"
-	"github.com/torkelo/grafana-pro/pkg/server"
+
+	"github.com/torkelo/grafana-pro/pkg/log"
+	"github.com/torkelo/grafana-pro/pkg/middleware"
+	"github.com/torkelo/grafana-pro/pkg/routes"
 	"github.com/torkelo/grafana-pro/pkg/setting"
 )
 
@@ -18,23 +25,66 @@ var CmdWeb = cli.Command{
 	Flags:       []cli.Flag{},
 }
 
+func newMacaron() *macaron.Macaron {
+	m := macaron.New()
+	m.Use(middleware.Logger())
+	m.Use(macaron.Recovery())
+	m.Use(macaron.Static(
+		path.Join(setting.StaticRootPath, "public"),
+		macaron.StaticOptions{
+			SkipLogging: true,
+			Prefix:      "public",
+		},
+	))
+	m.Use(macaron.Static(
+		path.Join(setting.StaticRootPath, "public/app"),
+		macaron.StaticOptions{
+			SkipLogging: true,
+			Prefix:      "app",
+		},
+	))
+	m.Use(macaron.Static(
+		path.Join(setting.StaticRootPath, "public/img"),
+		macaron.StaticOptions{
+			SkipLogging: true,
+			Prefix:      "img",
+		},
+	))
+
+	m.Use(macaron.Renderer(macaron.RenderOptions{
+		Directory:  path.Join(setting.StaticRootPath, "views"),
+		IndentJSON: macaron.Env != macaron.PROD,
+		Delims:     macaron.Delims{Left: "[[", Right: "]]"},
+	}))
+
+	m.Use(middleware.GetContextHandler())
+	return m
+}
+
 func runWeb(*cli.Context) {
+	setting.NewConfigContext()
+	setting.InitServices()
+
 	log.Info("Starting Grafana-Pro v.1-alpha")
 
-	setting.NewConfigContext()
+	m := newMacaron()
 
-	cfg := configuration.NewCfg(setting.HttpPort)
-	server, err := server.NewServer(cfg)
-	if err != nil {
-		time.Sleep(time.Second)
-		panic(err)
+	// index
+	m.Get("/", routes.Index)
+
+	var err error
+	listenAddr := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort)
+	log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubUrl)
+	switch setting.Protocol {
+	case setting.HTTP:
+		err = http.ListenAndServe(listenAddr, m)
+	case setting.HTTPS:
+		err = http.ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m)
+	default:
+		log.Fatal(4, "Invalid protocol: %s", setting.Protocol)
 	}
 
-	err = server.ListenAndServe()
 	if err != nil {
-		log.Error("ListenAndServe failed: ", err)
+		log.Fatal(4, "Fail to start server: %v", err)
 	}
-
-	time.Sleep(time.Millisecond * 2000)
-
 }

+ 58 - 0
pkg/middleware/logger.go

@@ -0,0 +1,58 @@
+// Copyright 2013 Martini Authors
+// Copyright 2014 Unknwon
+//
+// 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
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// 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 middleware
+
+import (
+	"fmt"
+	"net/http"
+	"runtime"
+	"time"
+
+	"github.com/Unknwon/macaron"
+	"github.com/torkelo/grafana-pro/pkg/log"
+)
+
+var isWindows bool
+
+func init() {
+	isWindows = runtime.GOOS == "windows"
+}
+
+// Logger returns a middleware handler that logs the request as it goes in and the response as it goes out.
+func Logger() macaron.Handler {
+	return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) {
+		start := time.Now()
+
+		rw := res.(macaron.ResponseWriter)
+		c.Next()
+
+		content := fmt.Sprintf("Completed %s %v %s in %v", req.URL.Path, rw.Status(), http.StatusText(rw.Status()), time.Since(start))
+		if !isWindows {
+			switch rw.Status() {
+			case 200:
+				content = fmt.Sprintf("\033[1;32m%s\033[0m", content)
+			case 304:
+				return
+				content = fmt.Sprintf("\033[1;33m%s\033[0m", content)
+			case 404:
+				content = fmt.Sprintf("\033[1;31m%s\033[0m", content)
+			case 500:
+				content = fmt.Sprintf("\033[1;36m%s\033[0m", content)
+			}
+		}
+		log.Info(content)
+	}
+}

+ 52 - 0
pkg/middleware/middleware.go

@@ -0,0 +1,52 @@
+package middleware
+
+import (
+	"time"
+
+	"github.com/Unknwon/macaron"
+	"github.com/macaron-contrib/session"
+
+	"github.com/torkelo/grafana-pro/pkg/log"
+	"github.com/torkelo/grafana-pro/pkg/models"
+)
+
+type Context struct {
+	*macaron.Context
+	Session session.Store
+
+	Account     *models.Account
+	UserAccount *models.Account
+
+	IsSigned bool
+}
+
+func GetContextHandler() macaron.Handler {
+	return func(c *macaron.Context) {
+		ctx := &Context{
+			Context: c,
+		}
+
+		ctx.Data["PageStartTime"] = time.Now()
+
+		c.Map(ctx)
+	}
+}
+
+// Handle handles and logs error by given status.
+func (ctx *Context) Handle(status int, title string, err error) {
+	if err != nil {
+		log.Error(4, "%s: %v", title, err)
+		if macaron.Env != macaron.PROD {
+			ctx.Data["ErrorMsg"] = err
+		}
+	}
+
+	switch status {
+	case 404:
+		ctx.Data["Title"] = "Page Not Found"
+	case 500:
+		ctx.Data["Title"] = "Internal Server Error"
+	}
+
+	ctx.HTML(status, "index")
+}

+ 12 - 0
pkg/routes/index.go

@@ -0,0 +1,12 @@
+package routes
+
+import "github.com/torkelo/grafana-pro/pkg/middleware"
+
+func Index(ctx *middleware.Context) {
+	ctx.HTML(200, "index")
+}
+
+func NotFound(ctx *middleware.Context) {
+	ctx.Data["Title"] = "Page Not Found"
+	ctx.Handle(404, "index", nil)
+}

+ 0 - 7
pkg/routes/routes.go

@@ -1,7 +0,0 @@
-package routes
-
-import "github.com/torkelo/grafana-pro/pkg/setting"
-
-func GlobalInit() {
-	setting.NewConfigContext()
-}

+ 40 - 1
pkg/setting/setting.go

@@ -1,3 +1,6 @@
+// Copyright 2014 Unknwon
+// Copyright 2014 Torkel Ödegaard
+
 package setting
 
 import (
@@ -11,6 +14,8 @@ import (
 
 	"github.com/Unknwon/com"
 	"github.com/Unknwon/goconfig"
+	"github.com/macaron-contrib/session"
+
 	"github.com/torkelo/grafana-pro/pkg/log"
 )
 
@@ -39,7 +44,12 @@ var (
 	HttpAddr, HttpPort string
 	SshPort            int
 	CertFile, KeyFile  string
-	DisableRouterLog   bool
+	RouterLogging      bool
+	StaticRootPath     string
+
+	// Session settings.
+	SessionProvider string
+	SessionConfig   *session.Config
 
 	// Global setting objects.
 	Cfg          *goconfig.ConfigFile
@@ -127,4 +137,33 @@ func NewConfigContext() {
 	if port != "" {
 		HttpPort = port
 	}
+
+	StaticRootPath = Cfg.MustValue("server", "static_root_path", workDir)
+	RouterLogging = Cfg.MustBool("server", "router_logging", false)
+}
+
+func initSessionService() {
+	SessionProvider = Cfg.MustValueRange("session", "provider", "memory", []string{"memory", "file"})
+
+	SessionConfig = new(session.Config)
+	SessionConfig.ProviderConfig = strings.Trim(Cfg.MustValue("session", "provider_config"), "\" ")
+	SessionConfig.CookieName = Cfg.MustValue("session", "cookie_name", "grafana_pro_sess")
+	SessionConfig.CookiePath = AppSubUrl
+	SessionConfig.Secure = Cfg.MustBool("session", "cookie_secure")
+	SessionConfig.EnableSetCookie = Cfg.MustBool("session", "enable_set_cookie", true)
+	SessionConfig.Gclifetime = Cfg.MustInt64("session", "gc_interval_time", 86400)
+	SessionConfig.Maxlifetime = Cfg.MustInt64("session", "session_life_time", 86400)
+	SessionConfig.SessionIDHashFunc = Cfg.MustValueRange("session", "session_id_hashfunc",
+		"sha1", []string{"sha1", "sha256", "md5"})
+	SessionConfig.SessionIDHashKey = Cfg.MustValue("session", "session_id_hashkey", string(com.RandomCreateBytes(16)))
+
+	if SessionProvider == "file" {
+		os.MkdirAll(path.Dir(SessionConfig.ProviderConfig), os.ModePerm)
+	}
+
+	log.Info("Session Service Enabled")
+}
+
+func InitServices() {
+	initSessionService()
 }