-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
106 lines (94 loc) · 2.83 KB
/
router.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
package app
import (
"bytes"
"errors"
"fmt"
"time"
"github.com/buaazp/fasthttprouter"
"github.com/jmoiron/sqlx"
"github.com/valyala/fasthttp"
"zxq.co/ripple/rippleapi/common"
)
type router struct {
r *fasthttprouter.Router
}
func (r router) Method(path string, f func(md common.MethodData) common.CodeMessager, privilegesNeeded ...int) {
r.r.GET(path, wrap(Method(f, privilegesNeeded...)))
}
func (r router) POSTMethod(path string, f func(md common.MethodData) common.CodeMessager, privilegesNeeded ...int) {
r.r.POST(path, wrap(Method(f, privilegesNeeded...)))
}
func (r router) Peppy(path string, a func(c *fasthttp.RequestCtx, db *sqlx.DB)) {
r.r.GET(path, wrap(PeppyMethod(a)))
}
func (r router) GET(path string, handle fasthttp.RequestHandler) {
r.r.GET(path, wrap(handle))
}
func (r router) PlainGET(path string, handle fasthttp.RequestHandler) {
r.r.GET(path, handle)
}
const (
// \x1b is escape code for ESC
// <ESC>[<n>m is escape sequence for a certain colour
// no IP is written out because of the hundreds of possible ways to pass IPs
// to a request when using a reverse proxy
// this is partly inspired from gin, though made even more simplistic.
fmtString = "%s | %15s |\x1b[%sm %3d \x1b[0m %-7s %s\n"
// a kind of human readable RFC3339
timeFormat = "2006-01-02 15:04:05"
// color reference
// http://misc.flogisoft.com/bash/tip_colors_and_formatting
colorOk = "42" // green
colorError = "41" // red
)
// wrap returns a function that wraps around handle, providing middleware
// functionality to apply to all API calls, which is to say:
// - logging
// - panic recovery (reporting to sentry)
// - gzipping
func wrap(handle fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(c *fasthttp.RequestCtx) {
start := time.Now()
doggo.Incr("requests", nil, 1)
defer func() {
if rval := recover(); rval != nil {
var err error
switch rval := rval.(type) {
case string:
err = errors.New(rval)
case error:
err = rval
default:
err = fmt.Errorf("%v - %#v", rval, rval)
}
common.Err(c, err)
c.SetStatusCode(500)
c.SetBodyString(`{ "code": 500, "message": "something really bad happened" }`)
}
// switch color to colorError if statusCode is in [500;600)
color := colorOk
statusCode := c.Response.StatusCode()
if statusCode >= 500 && statusCode < 600 {
color = colorError
}
if bytes.Contains(c.Request.Header.Peek("Accept-Encoding"), s2b("gzip")) {
c.Response.Header.Add("Content-Encoding", "gzip")
c.Response.Header.Add("Vary", "Accept-Encoding")
b := c.Response.Body()
c.Response.ResetBody()
fasthttp.WriteGzip(c.Response.BodyWriter(), b)
}
// print stuff
fmt.Printf(
fmtString,
time.Now().Format(timeFormat),
time.Since(start).String(),
color,
statusCode,
c.Method(),
c.Path(),
)
}()
handle(c)
}
}