-
Notifications
You must be signed in to change notification settings - Fork 0
/
render.go
91 lines (84 loc) · 2.57 KB
/
render.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
// Package controller - Content managed by Project Forge, see [projectforge.md] for details.
package controller
import (
"fmt"
"net/http"
"time"
"github.com/pkg/errors"
"admini.dev/admini/app"
"admini.dev/admini/app/controller/cutil"
"admini.dev/admini/app/util"
"admini.dev/admini/views"
"admini.dev/admini/views/layout"
"admini.dev/admini/views/verror"
)
func Render(r *http.Request, as *app.State, page layout.Page, ps *cutil.PageState, breadcrumbs ...string) (string, error) {
defer func() {
x := recover()
if x != nil {
ps.LogError("error processing template: %+v", x)
ps.W.WriteHeader(http.StatusInternalServerError)
var ed *util.ErrorDetail
switch t := x.(type) {
case error:
ed = util.GetErrorDetail(t, ps.Admin)
default:
ed = &util.ErrorDetail{Type: fmt.Sprintf("%T", x), Message: fmt.Sprint(t)}
}
if t := fmt.Sprintf("%T", page); t != "*verror.Error" {
ps.Data = ed
_, err := Render(r, as, &verror.Error{Err: ed}, ps, breadcrumbs...)
if err != nil {
verror.WriteDetail(ps.W, ed, as, ps)
}
} else {
verror.WriteDetail(ps.W, ed, as, ps)
}
}
}()
var fn string
if r.URL.Query().Get("download") == "true" {
fn = ps.Action
}
maybeRender := func(ct string) (bool, error) {
switch {
case cutil.IsContentTypeCSV(ct):
_, err := cutil.RespondCSV(ps.W, fn, ps.Data)
return true, err
case cutil.IsContentTypeJSON(ct):
_, err := cutil.RespondJSON(ps.W, fn, ps.Data)
return true, err
case cutil.IsContentTypeTOML(ct):
_, err := cutil.RespondTOML(ps.W, ps.Action, ps.Data)
return true, err
case cutil.IsContentTypeXML(ct):
_, err := cutil.RespondXML(ps.W, fn, ps.Data)
return true, err
case cutil.IsContentTypeYAML(ct):
_, err := cutil.RespondYAML(ps.W, fn, ps.Data)
return true, err
case cutil.IsContentTypeDebug(ct):
_, err := cutil.RespondDebug(ps.W, r, as, fn, ps)
return true, err
}
return false, nil
}
ps.Breadcrumbs = append(ps.Breadcrumbs, breadcrumbs...)
ct := cutil.GetContentType(r)
if ps.Data != nil {
if handled, err := maybeRender(ct); handled || err != nil {
return "", err
}
}
startNanos := util.TimeCurrentNanos()
if ps.DefaultFormat == "" {
ps.W.Header().Set(cutil.HeaderContentType, "text/html; charset=UTF-8")
views.WriteRender(ps.W, page, as, ps)
ps.RenderElapsed = float64((util.TimeCurrentNanos()-startNanos)/int64(time.Microsecond)) / float64(1000)
return "", nil
}
if handled, err := maybeRender(ps.DefaultFormat); handled || err != nil {
return "", err
}
return "", errors.Errorf("unable to process format [%s]", ps.DefaultFormat)
}