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  }