github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/mux.go (about) 1 package goa 2 3 import ( 4 "net/http" 5 "net/url" 6 7 "github.com/dimfeld/httptreemux" 8 ) 9 10 type ( 11 // MuxHandler provides the low level implementation for an API endpoint. 12 // The values argument includes both the querystring and path parameter values. 13 MuxHandler func(http.ResponseWriter, *http.Request, url.Values) 14 15 // ServeMux is the interface implemented by the service request muxes. 16 // It implements http.Handler and makes it possible to register request handlers for 17 // specific HTTP methods and request path via the Handle method. 18 ServeMux interface { 19 http.Handler 20 // Handle sets the MuxHandler for a given HTTP method and path. 21 Handle(method, path string, handle MuxHandler) 22 // HandleNotFound sets the MuxHandler invoked for requests that don't match any 23 // handler registered with Handle. The values argument given to the handler is 24 // always nil. 25 HandleNotFound(handle MuxHandler) 26 // Lookup returns the MuxHandler associated with the given HTTP method and path. 27 Lookup(method, path string) MuxHandler 28 } 29 30 // Muxer implements an adapter that given a request handler can produce a mux handler. 31 Muxer interface { 32 MuxHandler(string, Handler, Unmarshaler) MuxHandler 33 } 34 35 // mux is the default ServeMux implementation. 36 mux struct { 37 router *httptreemux.TreeMux 38 handles map[string]MuxHandler 39 } 40 ) 41 42 // NewMux returns a Mux. 43 func NewMux() ServeMux { 44 r := httptreemux.New() 45 r.EscapeAddedRoutes = true 46 return &mux{ 47 router: r, 48 handles: make(map[string]MuxHandler), 49 } 50 } 51 52 // Handle sets the handler for the given verb and path. 53 func (m *mux) Handle(method, path string, handle MuxHandler) { 54 hthandle := func(rw http.ResponseWriter, req *http.Request, htparams map[string]string) { 55 params := req.URL.Query() 56 for n, p := range htparams { 57 params.Set(n, p) 58 } 59 handle(rw, req, params) 60 } 61 m.handles[method+path] = handle 62 m.router.Handle(method, path, hthandle) 63 } 64 65 // HandleNotFound sets the MuxHandler invoked for requests that don't match any 66 // handler registered with Handle. 67 func (m *mux) HandleNotFound(handle MuxHandler) { 68 nfh := func(rw http.ResponseWriter, req *http.Request) { 69 handle(rw, req, nil) 70 } 71 m.router.NotFoundHandler = nfh 72 mna := func(rw http.ResponseWriter, req *http.Request, methods map[string]httptreemux.HandlerFunc) { 73 handle(rw, req, nil) 74 } 75 m.router.MethodNotAllowedHandler = mna 76 } 77 78 // Lookup returns the MuxHandler associated with the given method and path. 79 func (m *mux) Lookup(method, path string) MuxHandler { 80 return m.handles[method+path] 81 } 82 83 // ServeHTTP is the function called back by the underlying HTTP server to handle incoming requests. 84 func (m *mux) ServeHTTP(rw http.ResponseWriter, req *http.Request) { 85 m.router.ServeHTTP(rw, req) 86 }