parent
97b2901e7d
commit
75234ebd31
40
main.go
40
main.go
|
@ -15,41 +15,36 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"flag"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"time"
|
||||
"flag"
|
||||
|
||||
"amuz.es/go/mnemonics/route"
|
||||
"amuz.es/go/mnemonics/util"
|
||||
"net/http"
|
||||
"github.com/flosch/pongo2"
|
||||
"os"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var argIp = flag.String("listen_ip", "", "IP to listen on, defaults to all IPs")
|
||||
var argPort = flag.Int("port", 8080, "port to listen")
|
||||
var maxProcs = flag.Int("max_procs", 0, "max number of CPUs that can be used simultaneously. Less than 1 for default (number of cores).")
|
||||
var logger = logrus.New()
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
setMaxProcs()
|
||||
util.InitLogger()
|
||||
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.New()
|
||||
|
||||
|
||||
r.Use(util.Ginrus(logrus.StandardLogger(), time.RFC3339, true))
|
||||
|
||||
// middleware settings
|
||||
r.Use(util.Ginrus(time.RFC3339, true))
|
||||
r.Use(gin.Recovery())
|
||||
|
||||
// not found handler
|
||||
r.NoRoute(func(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "page_404.html", pongo2.Context{})
|
||||
c.HTML(http.StatusOK, "page_404.html", util.Context{})
|
||||
})
|
||||
|
||||
|
||||
logger.Level = logrus.ErrorLevel
|
||||
logger.Out=os.Stderr
|
||||
r.Use(util.Ginrus(logger, time.RFC3339, false))
|
||||
r.StaticFS("/static", route.Static(""))
|
||||
|
||||
r.GET("/api", route.Api)
|
||||
|
@ -59,12 +54,15 @@ func main() {
|
|||
c.String(200, "OK! - mnemonics services are fully operational!")
|
||||
})
|
||||
|
||||
// Use pongo2gin.Default() for default options or pongo2gin.New()
|
||||
// if you need to use custom RenderOptions.
|
||||
r.HTMLRender = util.Default()
|
||||
if gin.IsDebugging() {
|
||||
r.HTMLRender = util.TemplateSourceDebug("asset/template")
|
||||
} else {
|
||||
r.HTMLRender = util.TemplateSourceRelease("")
|
||||
}
|
||||
|
||||
r.GET("/", route.Index)
|
||||
|
||||
logger.Error("bootstrapped application")
|
||||
util.Log().Error("bootstrapped application")
|
||||
|
||||
r.Run() // listen and server on 0.0.0.0:8080
|
||||
}
|
||||
|
@ -83,6 +81,6 @@ func setMaxProcs() {
|
|||
// Check if the setting was successful.
|
||||
actualNumProcs := runtime.GOMAXPROCS(0)
|
||||
if actualNumProcs != numProcs {
|
||||
logger.Warnf("Specified max procs of %v but using %v", numProcs, actualNumProcs)
|
||||
util.Log().Warnf("Specified max procs of %v but using %v", numProcs, actualNumProcs)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@ package route
|
|||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/flosch/pongo2"
|
||||
|
||||
"net/http"
|
||||
|
||||
"amuz.es/go/mnemonics/util"
|
||||
)
|
||||
|
||||
func Index(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "index.html", pongo2.Context{})
|
||||
c.HTML(http.StatusOK, "index.html", util.Context{})
|
||||
}
|
||||
|
|
|
@ -6,10 +6,25 @@ package util
|
|||
import (
|
||||
"time"
|
||||
|
||||
"os"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var logger = logrus.New()
|
||||
|
||||
func InitLogger() {
|
||||
// logging framework
|
||||
logger.Level = logrus.ErrorLevel
|
||||
logger.Out = os.Stderr
|
||||
}
|
||||
|
||||
func Log() *logrus.Logger {
|
||||
// logging framework
|
||||
return logger
|
||||
}
|
||||
|
||||
// Ginrus returns a gin.HandlerFunc (middleware) that logs requests using logrus.
|
||||
//
|
||||
// Requests with errors are logged using logrus.Error().
|
||||
|
@ -18,7 +33,7 @@ import (
|
|||
// It receives:
|
||||
// 1. A time package format string (e.g. time.RFC3339).
|
||||
// 2. A boolean stating whether to use UTC time zone or local.
|
||||
func Ginrus(logger *logrus.Logger, timeFormat string, utc bool) gin.HandlerFunc {
|
||||
func Ginrus(timeFormat string, utc bool) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
// some evil middlewares modify this values
|
125
util/renderer.go
125
util/renderer.go
|
@ -2,70 +2,99 @@ package util
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
"bytes"
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"amuz.es/go/mnemonics/bind/template"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gin-gonic/gin/render"
|
||||
)
|
||||
|
||||
// RenderOptions is used to configure the renderer.
|
||||
type RenderOptions struct {
|
||||
ContentType string
|
||||
type (
|
||||
PongoRelease struct {
|
||||
templateSet *pongo2.TemplateSet
|
||||
Path string
|
||||
}
|
||||
|
||||
PongoDebug struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
Pongo struct {
|
||||
Template *pongo2.Template
|
||||
Name string
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
Context pongo2.Context
|
||||
)
|
||||
|
||||
func TemplateSourceRelease(path string) *PongoRelease {
|
||||
ts := pongo2.NewSet(path, &memoryTemplateLoader{loaderFunc: template.Asset})
|
||||
return &PongoRelease{ts, path}
|
||||
}
|
||||
|
||||
// Pongo2Render is a custom Gin template renderer using Pongo2.
|
||||
type Pongo2Render struct {
|
||||
Options *RenderOptions
|
||||
Template *pongo2.Template
|
||||
Context pongo2.Context
|
||||
func (p PongoRelease) Instance(name string, data interface{}) render.Render {
|
||||
t := pongo2.Must(p.templateSet.FromFile(path.Join(p.Path, name)))
|
||||
|
||||
return Pongo{
|
||||
Template: t,
|
||||
Name: name,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
func TemplateSourceDebug(path string) *PongoDebug {
|
||||
return &PongoDebug{path}
|
||||
}
|
||||
|
||||
// New creates a new Pongo2Render instance with custom Options.
|
||||
func New(options RenderOptions) *Pongo2Render {
|
||||
return &Pongo2Render{
|
||||
Options: &options,
|
||||
func (p PongoDebug) Instance(name string, data interface{}) render.Render {
|
||||
|
||||
t := pongo2.Must(pongo2.FromFile(path.Join(p.Path, name)))
|
||||
return Pongo{
|
||||
Template: t,
|
||||
Name: name,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
// Default creates a Pongo2Render instance with default options.
|
||||
func Default() *Pongo2Render {
|
||||
return New(RenderOptions{
|
||||
ContentType: "text/html; charset=utf-8",
|
||||
})
|
||||
func (p Pongo) Render(w http.ResponseWriter) error {
|
||||
ctx := pongo2.Context(p.Data.(Context))
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
return p.Template.ExecuteWriter(ctx, w)
|
||||
}
|
||||
|
||||
// Instance should return a new Pongo2Render struct per request and prepare
|
||||
// the template by either loading it from disk or using pongo2's cache.
|
||||
func (p Pongo2Render) Instance(name string, data interface{}) render.Render {
|
||||
var templateResult *pongo2.Template
|
||||
// always read template files from disk if in debug mode, use cache otherwise.
|
||||
//if gin.Mode() == "debug" {Render
|
||||
// template = pongo2.Must(pongo2.FromFile(filename))
|
||||
//} else {
|
||||
// template = pongo2.Must(pongo2.FromCache(filename))
|
||||
//}
|
||||
templateContent:=template.MustAsset(name)
|
||||
type memoryTemplateLoader struct {
|
||||
loaderFunc func(path string) ([]byte, error)
|
||||
fallbackLoader *pongo2.TemplateLoader
|
||||
}
|
||||
|
||||
templateResult=pongo2.Must(pongo2.FromString(string(templateContent[:])))
|
||||
|
||||
return Pongo2Render{
|
||||
Template: templateResult,
|
||||
Context: data.(pongo2.Context),
|
||||
Options: p.Options,
|
||||
func (m memoryTemplateLoader) Abs(base, name string) string {
|
||||
if filepath.IsAbs(name) || base == "" {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
// Render should render the template to the response.
|
||||
func (p Pongo2Render) Render(w http.ResponseWriter) error {
|
||||
writeContentType(w, []string{p.Options.ContentType})
|
||||
err := p.Template.ExecuteWriter(p.Context, w)
|
||||
return err
|
||||
}
|
||||
|
||||
// writeContentType is also in the gin/render package but it has not been made
|
||||
// pubic so is repeated here, maybe convince the author to make this public.
|
||||
func writeContentType(w http.ResponseWriter, value []string) {
|
||||
header := w.Header()
|
||||
if val := header["Content-Type"]; len(val) == 0 {
|
||||
header["Content-Type"] = value
|
||||
if name == "" {
|
||||
return base
|
||||
}
|
||||
|
||||
return filepath.Dir(base) + string(filepath.Separator) + name
|
||||
}
|
||||
|
||||
func (m memoryTemplateLoader) Get(path string) (io.Reader, error) {
|
||||
|
||||
Log().Errorf("hello template %s", filepath.Clean(path))
|
||||
// t := pongo2.Must(p.templateSet.FromFile(path.Join(p.Path, name)))
|
||||
data, err := m.loaderFunc(path)
|
||||
if err != nil {
|
||||
if m.fallbackLoader != nil {
|
||||
return (*m.fallbackLoader).Get(path)
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bytes.NewReader(data), nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue