forked from rainycape/gondola
/
profile.go
91 lines (84 loc) · 1.97 KB
/
profile.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 app
import (
"bytes"
"compress/flate"
"encoding/json"
"strconv"
"strings"
"time"
"gnd.la/app/profile"
"gnd.la/encoding/base64"
)
type profileInfo struct {
Elapsed time.Duration `json:"e"`
Timings []*profile.Timing `json:"t"`
Remaining time.Duration `json:"-"`
}
func getProfileInfo(ctx *Context) *profileInfo {
return &profileInfo{Elapsed: ctx.Elapsed(), Timings: profile.Timings()}
}
func profileHeader(ctx *Context) string {
data, _ := json.Marshal(getProfileInfo(ctx))
var buf bytes.Buffer
w, _ := flate.NewWriter(&buf, flate.DefaultCompression)
w.Write(data)
w.Close()
return base64.Encode(buf.Bytes())
}
func shouldProfile(ctx *Context) bool {
if inDevServer {
return true
}
if req := ctx.R.Header.Get(profile.HeaderName); req != "" {
if req == "true" {
ctx.Header().Add(profile.HeaderName, "auth")
return false
}
signer, err := ctx.app.Signer([]byte(profile.Salt))
if err != nil {
return false
}
data, err := signer.Unsign(req)
if err == nil {
parts := strings.Split(string(data), ":")
if len(parts) == 2 {
key := "profile-" + parts[1]
var seen bool
if ctx.Cache().Get(key, &seen) == nil && seen {
return false
}
ts, err := strconv.ParseInt(parts[0], 10, 64)
if err == nil {
delta := time.Now().Unix() - ts
if delta >= -300 && delta <= 300 {
ctx.Cache().Set(key, true, 300)
return true
}
}
}
}
ctx.Header().Add(profile.HeaderName, "denied")
}
return false
}
func profileInfoHandler(ctx *Context) {
var info *profileInfo
data := ctx.RequireFormValue("data")
if err := json.Unmarshal([]byte(data), &info); err != nil {
panic(err)
}
info.Remaining = info.Elapsed
for _, v := range info.Timings {
info.Remaining -= v.Total()
}
t := newInternalTemplate(ctx.app)
if err := t.parse("profile_info.html", nil); err != nil {
panic(err)
}
if err := t.prepare(); err != nil {
panic(err)
}
if err := t.Execute(ctx, info); err != nil {
panic(err)
}
}