1
0
mirror of https://github.com/kataras/iris.git synced 2026-01-07 20:17:05 +00:00

accesslog: NEW log broker and many more features

some fixes about context clone, fix response recorder concurrent access, fix reload views with only ParseTemplate and more
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-09-09 14:43:26 +03:00
parent fb7627256a
commit b77227a0f9
15 changed files with 359 additions and 49 deletions

View File

@@ -110,6 +110,11 @@ type noOpFS struct{}
func (fs noOpFS) Open(name string) (http.File, error) { return nil, nil }
func isNoOpFS(fs http.FileSystem) bool {
_, ok := fs.(noOpFS)
return ok
}
// fixes: "invalid character in file path"
// on amber engine (it uses the virtual fs directly
// and it uses filepath instead of the path package...).

View File

@@ -32,11 +32,18 @@ type HTMLEngine struct {
funcs template.FuncMap
//
middleware func(name string, contents []byte) (string, error)
Templates *template.Template
middleware func(name string, contents []byte) (string, error)
Templates *template.Template
customCache []customTmp // required to load them again if reload is true.
//
}
type customTmp struct {
name string
contents []byte
funcs template.FuncMap
}
var (
_ Engine = (*HTMLEngine)(nil)
_ EngineFuncer = (*HTMLEngine)(nil)
@@ -215,6 +222,17 @@ func (s *HTMLEngine) Funcs(funcMap template.FuncMap) *HTMLEngine {
//
// Returns an error if something bad happens, caller is responsible to handle that.
func (s *HTMLEngine) Load() error {
s.rmu.Lock()
defer s.rmu.Unlock()
return s.load()
}
func (s *HTMLEngine) load() error {
if err := s.reloadCustomTemplates(); err != nil {
return err
}
return walk(s.fs, s.rootDir, func(path string, info os.FileInfo, err error) error {
if info == nil || info.IsDir() {
return nil
@@ -231,15 +249,35 @@ func (s *HTMLEngine) Load() error {
return fmt.Errorf("%s: %w", path, err)
}
return s.ParseTemplate(path, buf, nil)
return s.parseTemplate(path, buf, nil)
})
}
func (s *HTMLEngine) reloadCustomTemplates() error {
for _, tmpl := range s.customCache {
if err := s.parseTemplate(tmpl.name, tmpl.contents, tmpl.funcs); err != nil {
return err
}
}
return nil
}
// ParseTemplate adds a custom template to the root template.
func (s *HTMLEngine) ParseTemplate(name string, contents []byte, funcs template.FuncMap) (err error) {
s.rmu.Lock()
defer s.rmu.Unlock()
s.customCache = append(s.customCache, customTmp{
name: name,
contents: contents,
funcs: funcs,
})
return s.parseTemplate(name, contents, funcs)
}
func (s *HTMLEngine) parseTemplate(name string, contents []byte, funcs template.FuncMap) (err error) {
s.initRootTmpl()
name = strings.TrimPrefix(name, "/")
@@ -270,6 +308,7 @@ func (s *HTMLEngine) initRootTmpl() { // protected by the caller.
// the root template should be the same,
// no matter how many reloads as the
// following unexported fields cannot be modified.
// However, on reload they should be cleared otherwise we get an error.
s.Templates = template.New(s.rootDir)
s.Templates.Delims(s.left, s.right)
}
@@ -349,7 +388,14 @@ func (s *HTMLEngine) runtimeFuncsFor(t *template.Template, name string, binding
func (s *HTMLEngine) ExecuteWriter(w io.Writer, name string, layout string, bindingData interface{}) error {
// re-parse the templates if reload is enabled.
if s.reload {
if err := s.Load(); err != nil {
s.rmu.Lock()
defer s.rmu.Unlock()
s.Templates = nil
// we lose the templates parsed manually, so store them when it's called
// in order for load to take care of them too.
if err := s.load(); err != nil {
return err
}
}

View File

@@ -178,9 +178,6 @@ func (s *JetEngine) AddVar(key string, value interface{}) {
// not safe concurrent access across clients, use it only on development state.
func (s *JetEngine) Reload(developmentMode bool) *JetEngine {
s.developmentMode = developmentMode
if s.Set != nil {
s.Set.SetDevelopmentMode(developmentMode)
}
return s
}
@@ -215,7 +212,6 @@ func (l *jetLoader) Exists(name string) (string, bool) {
// Load should load the templates from a physical system directory or by an embedded one (assets/go-bindata).
func (s *JetEngine) Load() error {
s.initSet()
// Note that, unlike the rest of template engines implementations,
// we don't call the Set.GetTemplate to parse the templates,
// we let it to the jet template parser itself which does that at serve-time and caches each template by itself.
@@ -236,7 +232,12 @@ func (s *JetEngine) initSet() {
s.mu.Lock()
if s.Set == nil {
s.Set = jet.NewHTMLSetLoader(s.loader)
s.Set.SetDevelopmentMode(s.developmentMode)
if s.developmentMode && !isNoOpFS(s.fs) {
// this check is made to avoid jet's fs lookup on noOp fs (nil passed by the developer).
// This can be produced when nil fs passed
// and only `ParseTemplate` is used.
s.Set.SetDevelopmentMode(true)
}
if s.vars != nil {
for key, value := range s.vars {