1
2
3
4
5
6
7
8
9
10
11
12
13
14 package route
15
16 import (
17 "context"
18 "net/http"
19
20 "github.com/julienschmidt/httprouter"
21 )
22
23 type param string
24
25
26
27 func Param(ctx context.Context, p string) string {
28 if v := ctx.Value(param(p)); v != nil {
29 return v.(string)
30 }
31 return ""
32 }
33
34
35 func WithParam(ctx context.Context, p, v string) context.Context {
36 return context.WithValue(ctx, param(p), v)
37 }
38
39
40
41 type Router struct {
42 rtr *httprouter.Router
43 prefix string
44 instrh func(handlerName string, handler http.HandlerFunc) http.HandlerFunc
45 }
46
47
48 func New() *Router {
49 return &Router{
50 rtr: httprouter.New(),
51 }
52 }
53
54
55 func (r *Router) WithInstrumentation(instrh func(handlerName string, handler http.HandlerFunc) http.HandlerFunc) *Router {
56 if r.instrh != nil {
57 newInstrh := instrh
58 instrh = func(handlerName string, handler http.HandlerFunc) http.HandlerFunc {
59 return newInstrh(handlerName, r.instrh(handlerName, handler))
60 }
61 }
62 return &Router{rtr: r.rtr, prefix: r.prefix, instrh: instrh}
63 }
64
65
66 func (r *Router) WithPrefix(prefix string) *Router {
67 return &Router{rtr: r.rtr, prefix: r.prefix + prefix, instrh: r.instrh}
68 }
69
70
71 func (r *Router) handle(handlerName string, h http.HandlerFunc) httprouter.Handle {
72 if r.instrh != nil {
73
74 h = r.instrh(handlerName, h)
75 }
76 return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
77 ctx, cancel := context.WithCancel(req.Context())
78 defer cancel()
79
80 for _, p := range params {
81 ctx = context.WithValue(ctx, param(p.Key), p.Value)
82 }
83 h(w, req.WithContext(ctx))
84 }
85 }
86
87
88 func (r *Router) Get(path string, h http.HandlerFunc) {
89 r.rtr.GET(r.prefix+path, r.handle(path, h))
90 }
91
92
93 func (r *Router) Options(path string, h http.HandlerFunc) {
94 r.rtr.OPTIONS(r.prefix+path, r.handle(path, h))
95 }
96
97
98 func (r *Router) Del(path string, h http.HandlerFunc) {
99 r.rtr.DELETE(r.prefix+path, r.handle(path, h))
100 }
101
102
103 func (r *Router) Put(path string, h http.HandlerFunc) {
104 r.rtr.PUT(r.prefix+path, r.handle(path, h))
105 }
106
107
108 func (r *Router) Post(path string, h http.HandlerFunc) {
109 r.rtr.POST(r.prefix+path, r.handle(path, h))
110 }
111
112
113 func (r *Router) Head(path string, h http.HandlerFunc) {
114 r.rtr.HEAD(r.prefix+path, r.handle(path, h))
115 }
116
117
118
119
120 func (r *Router) Redirect(w http.ResponseWriter, req *http.Request, path string, code int) {
121 http.Redirect(w, req, r.prefix+path, code)
122 }
123
124
125 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
126 r.rtr.ServeHTTP(w, req)
127 }
128
129
130
131 func FileServe(dir string) http.HandlerFunc {
132 fs := http.FileServer(http.Dir(dir))
133
134 return func(w http.ResponseWriter, r *http.Request) {
135 r.URL.Path = Param(r.Context(), "filepath")
136 fs.ServeHTTP(w, r)
137 }
138 }
139
View as plain text