/
handler.go
134 lines (108 loc) · 3.2 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"embed"
"fmt"
"html/template"
"sync"
"time"
"github.com/gorilla/mux"
"github.com/kardianos/osext"
)
const (
BaseFilename = "_base.html"
)
//go:embed templates/*
var embeddedTemplates embed.FS
// handler provides global values that must be
// safe for concurrent use from multiple goroutines
// to each handler method.
type handler struct {
*Global
router *mux.Router
// Cached values / do not use directly. If they
// need to be dynamic in the future, put them
// under mutex protection.
assets *string
folder *string
// Mutex protected values
mu sync.RWMutex
template map[string]*template.Template
}
func (h *handler) Assets() string {
if h.assets == nil {
h.Global.log.Println("Initializing Assets")
glyphs := fmt.Sprintf("/%s", RandHeteroglyphs(10))
h.assets = &glyphs
}
return *h.assets
}
func (h *handler) Folder() string {
if h.folder == nil {
folder, err := osext.ExecutableFolder()
if err != nil {
panic(fmt.Errorf(`handlers.go:Folder: %s`, err))
}
h.folder = &folder
h.Global.log.Printf("The binary is running in folder %s\n", *h.folder)
}
return *h.folder
}
func (h *handler) Template(templateFilename string) *template.Template {
h.mu.RLock()
defer h.mu.RUnlock()
if h.template == nil {
func() {
h.mu.RUnlock()
h.mu.Lock()
defer func() {
h.mu.Unlock()
h.mu.RLock()
}()
h.Global.log.Println("Initializing HTML templates")
h.template = make(map[string]*template.Template, 0)
//h.template = template.New("unused") // Build off a blank canvas
/*
tpl, err := h.template.ParseGlob(fmt.Sprintf(`%s/templates/*.html`, h.Folder()))
if err != nil {
panic(fmt.Errorf(`handlers.go:Template: %s`, err))
}
*/
tpl, err := template.New(BaseFilename).Funcs(template.FuncMap{
"add": func(a, b int) int { return a + b },
"cleanDate": func(d time.Time) string { return d.Format("January 02, 2006") },
"year": func(d time.Time) string { return d.Format("2006") },
"noescape": func(s string) template.HTML {
return template.HTML(s)
},
}).ParseFS(embeddedTemplates, "templates/_*.html")
//}).ParseFiles(fmt.Sprintf(`%s/templates/%s`, h.Folder(), BaseFilename))
if err != nil {
h.Global.log.Printf("handlers.go:Template: %s\n", err)
panic(fmt.Errorf(`handlers.go:Template: %s`, err))
}
h.template[BaseFilename] = tpl
}()
}
// Prevent execution of the BaseFilename template, which would prevent future copies
templateName := templateFilename
if templateFilename == BaseFilename {
templateName = fmt.Sprintf("CLONE%s", BaseFilename)
}
// Specific sub-template has already been generated
if tpl, ok := h.template[templateName]; ok {
return tpl
}
// Generate a clone of the base template so you don't contaminate it with the
// derivative template's `define` statements.
h.Global.log.Println("Initializing HTML template for", templateFilename)
tpl, err := template.Must(h.template[BaseFilename].Clone()).ParseFS(embeddedTemplates, fmt.Sprintf(`templates/%s`, templateFilename))
if err != nil {
panic(fmt.Errorf(`handlers.go:Template: %s`, err))
}
h.mu.RUnlock()
h.mu.Lock()
h.template[templateName] = tpl
h.mu.Unlock()
h.mu.RLock()
return tpl
}