blob: 0886713c181da980750b7db1cd5847a26b447904 [file] [log] [blame]
Serge Bazanskicc25bdf2018-10-25 14:02:58 +02001package denco
2
3import (
4 "net/http"
5)
6
7// Mux represents a multiplexer for HTTP request.
8type Mux struct{}
9
10// NewMux returns a new Mux.
11func NewMux() *Mux {
12 return &Mux{}
13}
14
15// GET is shorthand of Mux.Handler("GET", path, handler).
16func (m *Mux) GET(path string, handler HandlerFunc) Handler {
17 return m.Handler("GET", path, handler)
18}
19
20// POST is shorthand of Mux.Handler("POST", path, handler).
21func (m *Mux) POST(path string, handler HandlerFunc) Handler {
22 return m.Handler("POST", path, handler)
23}
24
25// PUT is shorthand of Mux.Handler("PUT", path, handler).
26func (m *Mux) PUT(path string, handler HandlerFunc) Handler {
27 return m.Handler("PUT", path, handler)
28}
29
30// HEAD is shorthand of Mux.Handler("HEAD", path, handler).
31func (m *Mux) HEAD(path string, handler HandlerFunc) Handler {
32 return m.Handler("HEAD", path, handler)
33}
34
35// Handler returns a handler for HTTP method.
36func (m *Mux) Handler(method, path string, handler HandlerFunc) Handler {
37 return Handler{
38 Method: method,
39 Path: path,
40 Func: handler,
41 }
42}
43
44// Build builds a http.Handler.
45func (m *Mux) Build(handlers []Handler) (http.Handler, error) {
46 recordMap := make(map[string][]Record)
47 for _, h := range handlers {
48 recordMap[h.Method] = append(recordMap[h.Method], NewRecord(h.Path, h.Func))
49 }
50 mux := newServeMux()
51 for m, records := range recordMap {
52 router := New()
53 if err := router.Build(records); err != nil {
54 return nil, err
55 }
56 mux.routers[m] = router
57 }
58 return mux, nil
59}
60
61// Handler represents a handler of HTTP request.
62type Handler struct {
63 // Method is an HTTP method.
64 Method string
65
66 // Path is a routing path for handler.
67 Path string
68
69 // Func is a function of handler of HTTP request.
70 Func HandlerFunc
71}
72
73// The HandlerFunc type is aliased to type of handler function.
74type HandlerFunc func(w http.ResponseWriter, r *http.Request, params Params)
75
76type serveMux struct {
77 routers map[string]*Router
78}
79
80func newServeMux() *serveMux {
81 return &serveMux{
82 routers: make(map[string]*Router),
83 }
84}
85
86// ServeHTTP implements http.Handler interface.
87func (mux *serveMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
88 handler, params := mux.handler(r.Method, r.URL.Path)
89 handler(w, r, params)
90}
91
92func (mux *serveMux) handler(method, path string) (HandlerFunc, []Param) {
93 if router, found := mux.routers[method]; found {
94 if handler, params, found := router.Lookup(path); found {
95 return handler.(HandlerFunc), params
96 }
97 }
98 return NotFound, nil
99}
100
101// NotFound replies to the request with an HTTP 404 not found error.
102// NotFound is called when unknown HTTP method or a handler not found.
103// If you want to use the your own NotFound handler, please overwrite this variable.
104var NotFound = func(w http.ResponseWriter, r *http.Request, _ Params) {
105 http.NotFound(w, r)
106}