forked from plgd-dev/go-coap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathservermux.go
149 lines (129 loc) · 4.09 KB
/
servermux.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Package coap provides a CoAP client and server.
package coap
import (
"errors"
"sync"
)
// ServeMux is an COAP request multiplexer. It matches the
// path name of each incoming request against a list of
// registered patterns add calls the handler for the pattern
// with same name.
// ServeMux is also safe for concurrent access from multiple goroutines.
type ServeMux struct {
z map[string]muxEntry
m *sync.RWMutex
defaultHandler Handler
}
type muxEntry struct {
h Handler
pattern string
}
// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux {
return &ServeMux{z: make(map[string]muxEntry), m: new(sync.RWMutex), defaultHandler: HandlerFunc(HandleFailed)}
}
// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = NewServeMux()
// Does path match pattern?
func pathMatch(pattern, path string) bool {
if len(pattern) == 0 {
// should not happen
return false
}
n := len(pattern)
if pattern[n-1] != '/' {
return pattern == path
}
return len(path) >= n && path[0:n] == pattern
}
// Find a handler on a handler map given a path string
// Most-specific (longest) pattern wins
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
mux.m.RLock()
defer mux.m.RUnlock()
var n = 0
for k, v := range mux.z {
if !pathMatch(k, path) {
continue
}
if h == nil || len(k) > n {
n = len(k)
h = v.h
pattern = v.pattern
}
}
return
}
// Handle adds a handler to the ServeMux for pattern.
func (mux *ServeMux) Handle(pattern string, handler Handler) error {
for pattern != "" && pattern[0] == '/' {
pattern = pattern[1:]
}
if pattern == "" {
return errors.New("invalid pattern")
}
if handler == nil {
return errors.New("nil handler")
}
mux.m.Lock()
mux.z[pattern] = muxEntry{h: handler, pattern: pattern}
mux.m.Unlock()
return nil
}
// DefaultHandle set default handler to the ServeMux
func (mux *ServeMux) DefaultHandle(handler Handler) {
mux.m.Lock()
mux.defaultHandler = handler
mux.m.Unlock()
}
// HandleFunc adds a handler function to the ServeMux for pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(w ResponseWriter, r *Request)) {
mux.Handle(pattern, HandlerFunc(handler))
}
// DefaultHandleFunc set a default handler function to the ServeMux.
func (mux *ServeMux) DefaultHandleFunc(handler func(w ResponseWriter, r *Request)) {
mux.DefaultHandle(HandlerFunc(handler))
}
// HandleRemove deregistrars the handler specific for pattern from the ServeMux.
func (mux *ServeMux) HandleRemove(pattern string) error {
if pattern == "" {
return errors.New("invalid pattern")
}
mux.m.Lock()
delete(mux.z, pattern)
mux.m.Unlock()
return nil
}
// ServeCOAP dispatches the request to the handler whose
// pattern most closely matches the request message. If DefaultServeMux
// is used the correct thing for DS queries is done: a possible parent
// is sought.
// If no handler is found a standard NotFound message is returned
func (mux *ServeMux) ServeCOAP(w ResponseWriter, r *Request) {
h, _ := mux.match(r.Msg.PathString())
if h == nil {
h = mux.defaultHandler
if h == nil {
h = failedHandler()
}
}
h.ServeCOAP(w, r)
}
// Handle registers the handler with the given pattern
// in the DefaultServeMux. The documentation for
// ServeMux explains how patterns are matched.
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
// HandleFunc registers the handler function with the given pattern
// in the DefaultServeMux.
func HandleFunc(pattern string, handler func(w ResponseWriter, r *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
// HandleRemove deregisters the handle with the given pattern
// in the DefaultServeMux.
func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
// DefaultHandle set the default handler in the DefaultServeMux.
func DefaultHandle(handler Handler) { DefaultServeMux.DefaultHandle(handler) }
// DefaultHandleFunc set the default handler in the DefaultServeMux.
func DefaultHandleFunc(handler func(w ResponseWriter, r *Request)) {
DefaultServeMux.DefaultHandleFunc(handler)
}