mirror of
https://github.com/tarampampam/error-pages.git
synced 2024-08-30 18:22:40 +00:00
103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
package tpl
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
)
|
|
|
|
// Annotator allows to annotate error code.
|
|
type Annotator struct {
|
|
Message string
|
|
Description string
|
|
}
|
|
|
|
// Errors is a "cached storage" for the rendered error pages for the different templates and codes.
|
|
type Errors struct {
|
|
templates map[string][]byte
|
|
codes map[string]Annotator
|
|
|
|
cacheMu sync.RWMutex
|
|
cache map[string]map[string][]byte // map[template]map[code]content
|
|
}
|
|
|
|
// NewErrors creates new Errors.
|
|
func NewErrors(templates map[string][]byte, codes map[string]Annotator) *Errors {
|
|
return &Errors{
|
|
templates: templates,
|
|
codes: codes,
|
|
cache: make(map[string]map[string][]byte),
|
|
}
|
|
}
|
|
|
|
func (e *Errors) existsInCache(template, code string) ([]byte, bool) {
|
|
e.cacheMu.RLock()
|
|
defer e.cacheMu.RUnlock()
|
|
|
|
if codes, tplOk := e.cache[template]; tplOk {
|
|
if content, codeOk := codes[code]; codeOk {
|
|
return content, true
|
|
}
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
func (e *Errors) putInCache(template, code string) error {
|
|
if _, ok := e.templates[template]; !ok {
|
|
return errors.New("template \"" + template + "\" does not exists")
|
|
}
|
|
|
|
if _, ok := e.codes[code]; !ok {
|
|
return errors.New("code \"" + code + "\" does not exists")
|
|
}
|
|
|
|
e.cacheMu.Lock()
|
|
defer e.cacheMu.Unlock()
|
|
|
|
if _, ok := e.cache[template]; !ok {
|
|
e.cache[template] = make(map[string][]byte)
|
|
}
|
|
|
|
e.cache[template][code] = Replace(e.templates[template], Replaces{
|
|
Code: code,
|
|
Message: e.codes[code].Message,
|
|
Description: e.codes[code].Description,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// Get the rendered error page content.
|
|
func (e *Errors) Get(template, code string) ([]byte, error) {
|
|
if content, ok := e.existsInCache(template, code); ok {
|
|
return content, nil
|
|
}
|
|
|
|
if err := e.putInCache(template, code); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
e.cacheMu.RLock()
|
|
defer e.cacheMu.RUnlock()
|
|
|
|
return e.cache[template][code], nil
|
|
}
|
|
|
|
// VisitAll allows to iterate all possible error pages and templates.
|
|
func (e *Errors) VisitAll(fn func(template, code string, content []byte) error) error {
|
|
for tpl := range e.templates {
|
|
for code := range e.codes {
|
|
content, err := e.Get(tpl, code)
|
|
if err != nil {
|
|
return err // will never happen
|
|
}
|
|
|
|
if err = fn(tpl, code, content); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|