1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-18 02:17:05 +00:00
Former-commit-id: 292d155c877ba3f9d1210db54c3df3fedd1d0c1c
This commit is contained in:
Gerasimos (Makis) Maropoulos
2018-01-15 00:54:01 +02:00
parent ad9c76adb3
commit a19e570c8a
19 changed files with 154 additions and 47 deletions

View File

@@ -20,9 +20,8 @@ type AmberEngine struct {
namesFn func() []string // for embedded, in combination with directory & extension
reload bool
//
rmu sync.RWMutex // locks for funcs
rmu sync.RWMutex // locks for `ExecuteWiter` when `reload` is true.
funcs map[string]interface{}
mu sync.Mutex // locks for template files load
templateCache map[string]*template.Template
}
@@ -57,6 +56,10 @@ func (s *AmberEngine) Binary(assetFn func(name string) ([]byte, error), namesFn
// Reload if setted to true the templates are reloading on each render,
// use it when you're in development and you're boring of restarting
// the whole app when you edit a template file.
//
// Note that if `true` is passed then only one `View -> ExecuteWriter` will be render each time,
// no concurrent access across clients, use it only on development status.
// It's good to be used side by side with the https://github.com/kataras/rizla reloader for go source files.
func (s *AmberEngine) Reload(developmentMode bool) *AmberEngine {
s.reload = developmentMode
return s
@@ -116,8 +119,6 @@ func (s *AmberEngine) loadDirectory() error {
templates, err := amber.CompileDir(dir, opt, amber.DefaultOptions) // this returns the map with stripped extension, we want extension so we copy the map
if err == nil {
s.mu.Lock()
defer s.mu.Unlock()
s.templateCache = make(map[string]*template.Template)
for k, v := range templates {
name := filepath.ToSlash(k + opt.Ext)
@@ -155,9 +156,6 @@ func (s *AmberEngine) loadAssets() error {
}
amber.FuncMap = funcs //set the funcs
s.mu.Lock()
defer s.mu.Unlock()
names := namesFn()
for _, path := range names {
@@ -192,21 +190,22 @@ func (s *AmberEngine) loadAssets() error {
}
func (s *AmberEngine) fromCache(relativeName string) *template.Template {
s.mu.Lock()
tmpl, ok := s.templateCache[relativeName]
if ok {
s.mu.Unlock()
return tmpl
}
s.mu.Unlock()
return nil
}
// ExecuteWriter executes a template and writes its result to the w writer.
// layout here is useless.
func (s *AmberEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
// reload the templates if reload configuration field is true
// re-parse the templates if reload is enabled.
if s.reload {
// locks to fix #872, it's the simplest solution and the most correct,
// to execute writers with "wait list", one at a time.
s.rmu.Lock()
defer s.rmu.Unlock()
if err := s.Load(); err != nil {
return err
}

View File

@@ -106,7 +106,7 @@ type DjangoEngine struct {
namesFn func() []string // for embedded, in combination with directory & extension
reload bool
//
rmu sync.RWMutex // locks for filters and globals
rmu sync.RWMutex // locks for filters, globals and `ExecuteWiter` when `reload` is true.
// filters for pongo2, map[name of the filter] the filter function . The filters are auto register
filters map[string]FilterFunction
// globals share context fields between templates. https://github.com/flosch/pongo2/issues/35
@@ -147,6 +147,10 @@ func (s *DjangoEngine) Binary(assetFn func(name string) ([]byte, error), namesFn
// Reload if setted to true the templates are reloading on each render,
// use it when you're in development and you're boring of restarting
// the whole app when you edit a template file.
//
// Note that if `true` is passed then only one `View -> ExecuteWriter` will be render each time,
// no concurrent access across clients, use it only on development status.
// It's good to be used side by side with the https://github.com/kataras/rizla reloader for go source files.
func (s *DjangoEngine) Reload(developmentMode bool) *DjangoEngine {
s.reload = developmentMode
return s
@@ -373,8 +377,12 @@ func (s *DjangoEngine) fromCache(relativeName string) *pongo2.Template {
// ExecuteWriter executes a templates and write its results to the w writer
// layout here is useless.
func (s *DjangoEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
// reload the templates if reload configuration field is true
// re-parse the templates if reload is enabled.
if s.reload {
// locks to fix #872, it's the simplest solution and the most correct,
// to execute writers with "wait list", one at a time.
s.rmu.Lock()
defer s.rmu.Unlock()
if err := s.Load(); err != nil {
return err
}

View File

@@ -22,9 +22,8 @@ type HandlebarsEngine struct {
reload bool // if true, each time the ExecuteWriter is called the templates will be reloaded.
// parser configuration
layout string
rmu sync.RWMutex // locks for helpers
rmu sync.RWMutex // locks for helpers and `ExecuteWiter` when `reload` is true.
helpers map[string]interface{}
mu sync.Mutex // locks for template files load
templateCache map[string]*raymond.Template
}
@@ -66,6 +65,10 @@ func (s *HandlebarsEngine) Binary(assetFn func(name string) ([]byte, error), nam
// Reload if setted to true the templates are reloading on each render,
// use it when you're in development and you're boring of restarting
// the whole app when you edit a template file.
//
// Note that if `true` is passed then only one `View -> ExecuteWriter` will be render each time,
// no concurrent access across clients, use it only on development status.
// It's good to be used side by side with the https://github.com/kataras/rizla reloader for go source files.
func (s *HandlebarsEngine) Reload(developmentMode bool) *HandlebarsEngine {
s.reload = developmentMode
return s
@@ -123,8 +126,7 @@ func (s *HandlebarsEngine) loadDirectory() error {
// the render works like {{ render "myfile.html" theContext.PartialContext}}
// instead of the html/template engine which works like {{ render "myfile.html"}} and accepts the parent binding, with handlebars we can't do that because of lack of runtime helpers (dublicate error)
s.mu.Lock()
defer s.mu.Unlock()
var templateErr error
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if info == nil || info.IsDir() {
@@ -181,9 +183,6 @@ func (s *HandlebarsEngine) loadAssets() error {
}
var templateErr error
s.mu.Lock()
defer s.mu.Unlock()
names := namesFn()
for _, path := range names {
if !strings.HasPrefix(path, virtualDirectory) {
@@ -219,14 +218,11 @@ func (s *HandlebarsEngine) loadAssets() error {
}
func (s *HandlebarsEngine) fromCache(relativeName string) *raymond.Template {
s.mu.Lock()
tmpl, ok := s.templateCache[relativeName]
if ok {
s.mu.Unlock()
return tmpl
if !ok {
return nil
}
s.mu.Unlock()
return nil
return tmpl
}
func (s *HandlebarsEngine) executeTemplateBuf(name string, binding interface{}) (string, error) {
@@ -238,8 +234,12 @@ func (s *HandlebarsEngine) executeTemplateBuf(name string, binding interface{})
// ExecuteWriter executes a template and writes its result to the w writer.
func (s *HandlebarsEngine) ExecuteWriter(w io.Writer, filename string, layout string, bindingData interface{}) error {
// reload the templates if reload configuration field is true
// re-parse the templates if reload is enabled.
if s.reload {
// locks to fix #872, it's the simplest solution and the most correct,
// to execute writers with "wait list", one at a time.
s.rmu.Lock()
defer s.rmu.Unlock()
if err := s.Load(); err != nil {
return err
}

View File

@@ -10,6 +10,7 @@ import (
"path/filepath"
"strings"
"sync"
"time"
)
type (
@@ -20,7 +21,7 @@ type (
extension string
assetFn func(name string) ([]byte, error) // for embedded, in combination with directory & extension
namesFn func() []string // for embedded, in combination with directory & extension
reload bool // if true, each time the ExecuteWriter is called the templates will be reloaded.
reload bool // if true, each time the ExecuteWriter is called the templates will be reloaded, each ExecuteWriter waits to be finished before writing to a new one.
// parser configuration
options []string // text options
left string
@@ -32,7 +33,6 @@ type (
//
middleware func(name string, contents string) (string, error)
mu sync.Mutex // locks for template files loader
Templates *template.Template
//
}
@@ -94,6 +94,10 @@ func (s *HTMLEngine) Binary(assetFn func(name string) ([]byte, error), namesFn f
// Reload if setted to true the templates are reloading on each render,
// use it when you're in development and you're boring of restarting
// the whole app when you edit a template file.
//
// Note that if `true` is passed then only one `View -> ExecuteWriter` will be render each time,
// no concurrent access across clients, use it only on development status.
// It's good to be used side by side with the https://github.com/kataras/rizla reloader for go source files.
func (s *HTMLEngine) Reload(developmentMode bool) *HTMLEngine {
s.reload = developmentMode
return s
@@ -118,9 +122,9 @@ func (s *HTMLEngine) Reload(developmentMode bool) *HTMLEngine {
// Execution stops immediately with an error.
//
func (s *HTMLEngine) Option(opt ...string) *HTMLEngine {
s.mu.Lock()
s.rmu.Lock()
s.options = append(s.options, opt...)
s.mu.Unlock()
s.rmu.Unlock()
return s
}
@@ -180,6 +184,15 @@ func (s *HTMLEngine) AddFunc(funcName string, funcBody interface{}) {
//
// Returns an error if something bad happens, user is responsible to catch it.
func (s *HTMLEngine) Load() error {
// No need to make this with a complicated and "pro" way, just add lockers to the `ExecuteWriter`.
// if `Reload(true)` and add a note for non conc access on dev mode.
// atomic.StoreUint32(&s.isLoading, 1)
// s.rmu.Lock()
// defer func() {
// s.rmu.Unlock()
// atomic.StoreUint32(&s.isLoading, 0)
// }()
if s.assetFn != nil && s.namesFn != nil {
// NOT NECESSARY "fix" of https://github.com/kataras/iris/issues/784,
// IT'S BAD CODE WRITTEN WE KEEP HERE ONLY FOR A REMINDER
@@ -256,10 +269,10 @@ func (s *HTMLEngine) loadDirectory() error {
templateErr = err
return err
}
s.mu.Lock()
//s.mu.Lock()
// Add our funcmaps.
_, err = tmpl.Funcs(emptyFuncs).Funcs(s.funcs).Parse(contents)
s.mu.Unlock()
//s.mu.Unlock()
if err != nil {
templateErr = err
return err
@@ -406,11 +419,10 @@ func (s *HTMLEngine) layoutFuncsFor(name string, binding interface{}) {
return template.HTML(buf.String()), err
},
}
s.rmu.RLock()
for k, v := range s.layoutFuncs {
funcs[k] = v
}
s.rmu.RUnlock()
if tpl := s.Templates.Lookup(name); tpl != nil {
tpl.Funcs(funcs)
}
@@ -429,10 +441,16 @@ func (s *HTMLEngine) runtimeFuncsFor(name string, binding interface{}) {
}
}
var zero = time.Time{}
// ExecuteWriter executes a template and writes its result to the w writer.
func (s *HTMLEngine) ExecuteWriter(w io.Writer, name string, layout string, bindingData interface{}) error {
// reload the templates if reload configuration field is true
// re-parse the templates if reload is enabled.
if s.reload {
// locks to fix #872, it's the simplest solution and the most correct,
// to execute writers with "wait list", one at a time.
s.rmu.Lock()
defer s.rmu.Unlock()
if err := s.Load(); err != nil {
return err
}