-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttprouter.go
89 lines (79 loc) · 2.17 KB
/
httprouter.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
package webtool
import (
"errors"
"fmt"
"html"
"log"
"net/http"
)
func NewHttpRouter() *HttpRouter {
return &HttpRouter{
pathMatch: NewPathMatch(),
basePath: "",
actions: make(map[string]ActionFunc),
errorFuncs: make(map[string]ErrorFunc),
}
}
type ErrorFunc func(string, http.ResponseWriter, *http.Request)
type HttpRouter struct {
pathMatch *PathMatch
basePath string
actions map[string]ActionFunc
errorFuncs map[string]ErrorFunc
}
func (self *HttpRouter) SetBasePath(basePath string) *HttpRouter {
self.basePath = basePath
return self
}
func (self *HttpRouter) SetError(errorCode string, errorFunc ErrorFunc) *HttpRouter {
self.errorFuncs[errorCode] = errorFunc
return self
}
func (self *HttpRouter) SetRoute(pathPattern string, action ActionFunc) *HttpRouter {
defaults := make(map[string]string)
defaults["action"] = "[a-z0-9_]+"
err := self.pathMatch.Parse(pathPattern, defaults)
if err != nil {
panic(err)
}
self.actions[pathPattern] = action
return self
}
func (self *HttpRouter) removeBasePathFrom(path string) string {
if len(path) >= len(self.basePath) && path[0:len(self.basePath)] == self.basePath {
p := path[len(self.basePath):]
return p
} else {
return ""
}
}
func (self *HttpRouter) GetAction(urlPath string) (Executor, error) {
path := self.removeBasePathFrom(urlPath)
pathPattern, matches, ok := self.pathMatch.Match(path)
e := Executor{}
if ok {
e.params = matches
e.action = self.actions[pathPattern]
return e, nil
}
return e, errors.New("action not found")
}
func (self *HttpRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
f, err := self.GetAction(r.URL.Path)
if err == nil {
message, err := f.Exec(w, r)
if IsActionError(err) {
self.errorFuncs[err.Code()](err.Error(), w, r)
}
log.Printf("result[%s]", message)
} else {
defaultFunc, ok := self.errorFuncs["default"]
if ok {
defaultFunc(r.URL.Path, w, r)
} else {
// fmt.Fprintf(w, "Error, %q\n", html.EscapeString(r.URL.Path))
http.Error(w, err.Error(), http.StatusInternalServerError)
log.Printf("handling %q: %v", r.RequestURI, err)
}
}
}