github.com/furusax0621/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  }