/
mux.go
120 lines (101 loc) · 2.36 KB
/
mux.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
package webc
import (
"net/http"
"strings"
"github.com/cagnosolutions/webc/util"
)
type controller func(http.ResponseWriter, *http.Request, *Context)
type route struct {
method string
path []string
handle controller
}
type Mux struct {
routes []*route
ctx *contextStore
static http.Handler
}
func NewMux(ctxid string, rate int64) *Mux {
return &Mux{
routes: make([]*route, 0),
ctx: NewContextStore(ctxid, rate),
static: http.StripPrefix("/static/", http.FileServer(http.Dir("static"))),
}
}
func (m *Mux) Serve(host string) {
m.ctx.gc()
if err := http.ListenAndServe(host, m); err != nil {
panic(err)
}
}
func (m *Mux) handle(method, path string, handler controller) {
m.routes = append(m.routes, &route{method, util.SliceString(path, '/'), handler})
}
func (m *Mux) Get(path string, handler controller) {
m.handle("GET", path, handler)
}
func (m *Mux) Put(path string, handler controller) {
m.handle("PUT", path, handler)
}
func (m *Mux) Post(path string, handler controller) {
m.handle("POST", path, handler)
}
func (m *Mux) Delete(path string, handler controller) {
m.handle("DELETE", path, handler)
}
func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// for now: ignore options and favicon
if r.Method == "OPTIONS" || r.URL.Path == "/favicon.ico" {
return
}
//handle static mapping
if r.Method == "GET" && strings.HasPrefix(r.URL.Path, "/static/") {
m.static.ServeHTTP(w, r)
return
}
for _, route := range m.routes {
if route.method == r.Method {
path := util.SliceString(r.URL.Path, '/')
if pathVars, ok := match(path, route.path); ok {
ctx := m.ctx.get(w, r)
ctx.SetPathVars(pathVars)
route.handle(w, r, ctx)
return
}
}
}
return
}
func match(req []string, pat []string) (map[string]string, bool) {
vals := make(map[string]string)
if len(req) != len(pat) {
return nil, false
}
for i, v := range pat {
if v[0] == ':' {
vals[v[1:len(v)]] = req[i]
} else if v != req[i] {
return nil, false
}
}
return vals, true
}
/*
func match(req []string, pat []string) (map[string]string, bool) {
v := make(map[string]string)
if len(req) == len(pat) {
for i := 0; i < len(pat); i++ {
if req[i] != pat[i] {
if pat[i][0] == ':' {
key := pat[i][1:len(pat[i])]
v[key] = req[i]
} else {
return nil, false
}
}
}
return v, true
}
return nil, false
}
*/