Serge Bazanski | cc25bdf | 2018-10-25 14:02:58 +0200 | [diff] [blame] | 1 | package denco |
| 2 | |
| 3 | import ( |
| 4 | "net/http" |
| 5 | ) |
| 6 | |
| 7 | // Mux represents a multiplexer for HTTP request. |
| 8 | type Mux struct{} |
| 9 | |
| 10 | // NewMux returns a new Mux. |
| 11 | func NewMux() *Mux { |
| 12 | return &Mux{} |
| 13 | } |
| 14 | |
| 15 | // GET is shorthand of Mux.Handler("GET", path, handler). |
| 16 | func (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). |
| 21 | func (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). |
| 26 | func (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). |
| 31 | func (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. |
| 36 | func (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. |
| 45 | func (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. |
| 62 | type 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. |
| 74 | type HandlerFunc func(w http.ResponseWriter, r *http.Request, params Params) |
| 75 | |
| 76 | type serveMux struct { |
| 77 | routers map[string]*Router |
| 78 | } |
| 79 | |
| 80 | func newServeMux() *serveMux { |
| 81 | return &serveMux{ |
| 82 | routers: make(map[string]*Router), |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | // ServeHTTP implements http.Handler interface. |
| 87 | func (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 | |
| 92 | func (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. |
| 104 | var NotFound = func(w http.ResponseWriter, r *http.Request, _ Params) { |
| 105 | http.NotFound(w, r) |
| 106 | } |