This repository has been archived by the owner on Dec 5, 2022. It is now read-only.
/
ace.go
126 lines (111 loc) · 3.53 KB
/
ace.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
// ace is a elsa middleware for ace
package ace
import (
"log"
"net/http"
"strings"
"github.com/yosssi/ace"
"github.com/LeKovr/elsa/mw/flow"
"github.com/LeKovr/elsa/pagedata"
"github.com/LeKovr/elsa/struct/page"
"github.com/LeKovr/go-base/dirtree"
)
// -----------------------------------------------------------------------------
// Flags defines local application flags
type Flags struct {
Prefix string `long:"ace_prefix" default:"/" description:"URL prefix to handle"`
Ext string `long:"ace_ext" default:".ace" description:"Template extention"`
Templates string `long:"ace_path" default:"templates/ace" description:"Dir where templates are"`
Error403 string `long:"ace_403" default:".error403" description:"Template for 403 error"`
Error404 string `long:"ace_404" default:".error404" description:"Template for 404 error"`
}
// -----------------------------------------------------------------------------
// Middleware is a struct that has a ServeHTTP method
type Middleware struct {
Log *log.Logger
Config *Flags
Tree *dirtree.Tree
IsLast bool // middleware is the last in chain, show errors and show 404 if no template
}
// -----------------------------------------------------------------------------
func New(logger *log.Logger, cfg *Flags, show404 bool) *Middleware {
tree, _ := dirtree.New(logger, cfg.Templates, cfg.Ext)
return &Middleware{Log: logger, Config: cfg, Tree: tree, IsLast: show404}
}
// -----------------------------------------------------------------------------
// The middleware handler
func (mw *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
var slug, tmplPath string
var attr page.Attr
if flow.Prohibited(r) {
if mw.IsLast {
mw.Log.Print("debug: Show 403")
w.WriteHeader(http.StatusForbidden)
tmplPath = mw.Config.Error403
} else {
next(w, r)
return
}
} else if flow.Finished(r) {
mw.Log.Print("debug: Flow is finished")
next(w, r)
return
} else {
// Regular request
ctx := r.Context()
data := ctx.Value("data")
if data != nil {
mw.Log.Print("debug: Show data from context")
attr = data.(page.Attr) //(data)
if attr.Ext() == mw.Config.Ext { // we serve this ext
slug = attr.Template()
} else if attr.Ext() != "" { // other engine will serve
next(w, r)
return
}
// Ext() == "" => any engine may serve, check request uri
}
// data == nil => check request uri
url := r.URL.Path
if slug == "" { // check request uri
inGame := strings.HasPrefix(url, mw.Config.Prefix)
if !inGame {
next(w, r)
return
} else {
slug = strings.TrimPrefix(url, mw.Config.Prefix)
}
}
mw.Log.Printf("debug: Requested page: %s", slug)
node, ok := mw.Tree.Node(slug, nil)
if !ok {
if mw.IsLast {
mw.Log.Print("debug: Show 404")
w.WriteHeader(http.StatusNotFound)
tmplPath = mw.Config.Error404
} else {
next(w, r)
return
}
} else {
tmplPath = node.File.Path
}
}
tmpl := strings.TrimSuffix(tmplPath, mw.Config.Ext)
mw.Log.Printf("debug: Use template: %s", tmpl)
tpl, err := ace.Load("layout", tmpl, &ace.Options{BaseDir: mw.Config.Templates})
mw.Log.Printf("debug: TMPL:%+v", tpl.Tree.Root)
var pageData interface{}
if attr != nil {
pageData = attr.Data
} else {
pageData = pagedata.New()
}
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else if err := tpl.Execute(w, pageData); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
flow.Finish(r)
next(w, r)
}