github.com/ManabuSeki/goa-v1@v1.4.3/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 // MethodNotAllowedHandler provides the implementation for an MethodNotAllowed 16 // handler. The values argument includes both the querystring and path parameter 17 // values. The methods argument includes both the allowed method identifier 18 // and the registered handler. 19 MethodNotAllowedHandler func(http.ResponseWriter, *http.Request, url.Values, map[string]httptreemux.HandlerFunc) 20 21 // ServeMux is the interface implemented by the service request muxes. 22 // It implements http.Handler and makes it possible to register request handlers for 23 // specific HTTP methods and request path via the Handle method. 24 ServeMux interface { 25 http.Handler 26 // Handle sets the MuxHandler for a given HTTP method and path. 27 Handle(method, path string, handle MuxHandler) 28 // HandleNotFound sets the MuxHandler invoked for requests that don't match any 29 // handler registered with Handle. The values argument given to the handler is 30 // always nil. 31 HandleNotFound(handle MuxHandler) 32 // HandleMethodNotAllowed sets the MethodNotAllowedHandler invoked for requests 33 // that match the path of a handler but not its HTTP method. The values argument 34 // given to the Handler is always nil. 35 HandleMethodNotAllowed(handle MethodNotAllowedHandler) 36 // Lookup returns the MuxHandler associated with the given HTTP method and path. 37 Lookup(method, path string) MuxHandler 38 } 39 40 // Muxer implements an adapter that given a request handler can produce a mux handler. 41 Muxer interface { 42 MuxHandler(string, Handler, Unmarshaler) MuxHandler 43 } 44 45 // mux is the default ServeMux implementation. 46 mux struct { 47 router *httptreemux.TreeMux 48 handles map[string]MuxHandler 49 } 50 ) 51 52 // NewMux returns a Mux. 53 func NewMux() ServeMux { 54 r := httptreemux.New() 55 r.EscapeAddedRoutes = true 56 return &mux{ 57 router: r, 58 handles: make(map[string]MuxHandler), 59 } 60 } 61 62 // Handle sets the handler for the given verb and path. 63 func (m *mux) Handle(method, path string, handle MuxHandler) { 64 hthandle := func(rw http.ResponseWriter, req *http.Request, htparams map[string]string) { 65 params := req.URL.Query() 66 for n, p := range htparams { 67 params.Set(n, p) 68 } 69 handle(rw, req, params) 70 } 71 m.handles[method+path] = handle 72 m.router.Handle(method, path, hthandle) 73 } 74 75 // HandleNotFound sets the MuxHandler invoked for requests that don't match any 76 // handler registered with Handle. 77 func (m *mux) HandleNotFound(handle MuxHandler) { 78 nfh := func(rw http.ResponseWriter, req *http.Request) { 79 handle(rw, req, nil) 80 } 81 m.router.NotFoundHandler = nfh 82 } 83 84 // HandleMethodNotAllowed sets the MuxHandler invoked for requests that match 85 // the path of a handler but not its HTTP method. 86 func (m *mux) HandleMethodNotAllowed(handle MethodNotAllowedHandler) { 87 mna := func(rw http.ResponseWriter, req *http.Request, methods map[string]httptreemux.HandlerFunc) { 88 handle(rw, req, nil, methods) 89 } 90 m.router.MethodNotAllowedHandler = mna 91 } 92 93 // Lookup returns the MuxHandler associated with the given method and path. 94 func (m *mux) Lookup(method, path string) MuxHandler { 95 return m.handles[method+path] 96 } 97 98 // ServeHTTP is the function called back by the underlying HTTP server to handle incoming requests. 99 func (m *mux) ServeHTTP(rw http.ResponseWriter, req *http.Request) { 100 m.router.ServeHTTP(rw, req) 101 }