Documentation ¶
Overview ¶
Package mux is a minimal http router that wraps the https://github.com/julienschmidt/httprouter. Example:
package main import ( "context" "log" "net/http" "os" "time" "github.com/google/uuid" "github.com/josestg/mux" ) func main() { requestIDMaker := new(IDMaker) shutdownChannel := make(chan os.Signal, 1) router := mux.NewRouter( requestIDMaker, shutdownChannel, logger, ) router.Get("/check", func(w http.ResponseWriter, r *http.Request) error { status := map[string]string{ "status": "running", } return mux.ToJSON(r.Context(), w, &status, http.StatusOK) }) router.With(auth).Post("/auth", func(w http.ResponseWriter, r *http.Request) error { data := struct { Status string }{ Status: "Authenticated", } return mux.ToJSON(r.Context(), w, &data, http.StatusOK) }) server := http.Server{ Addr: "0.0.0.0:8080", Handler: router, } routerErr := make(chan error, 1) go func() { log.Printf("server is listening on: %s", server.Addr) routerErr <- server.ListenAndServe() }() select { case <-shutdownChannel: if err := server.Shutdown(context.Background()); err != nil { _ = server.Close() } case err := <-routerErr: log.Printf("server not listening: %v", err) } } type IDMaker struct { } func (I IDMaker) NextRequestID() string { return uuid.NewString() } // logger is a logger middleware. func logger(handleFunc mux.HandleFunc) mux.HandleFunc { return func(w http.ResponseWriter, r *http.Request) error { state, err := mux.GetState(r.Context()) if err != nil { return mux.NewShutdownError(err.Error()) } log.Println("request started") defer func() { log.Printf("request completed: %v", time.Since(state.RequestCreated)) }() return handleFunc(w, r) } } // auth is a fake auth middleware. func auth(handleFunc mux.HandleFunc) mux.HandleFunc { return func(w http.ResponseWriter, r *http.Request) error { var body struct { Password string `json:"password"` } if err := mux.FromJSON(r.Body, &body); err != nil { return mux.NewShutdownError(err.Error()) } if body.Password != "secret" { resp := struct { Message string `json:"message"` }{ Message: "Invalid password", } return mux.ToJSON(r.Context(), w, &resp, http.StatusUnauthorized) } return handleFunc(w, r) } }
Index ¶
- Constants
- Variables
- func FromJSON(r io.Reader, v interface{}) error
- func IsShutdownError(err error) bool
- func NewShutdownError(msg string) error
- func ToJSON(ctx context.Context, w http.ResponseWriter, data interface{}, status int) error
- type HandleFunc
- type Middleware
- type Params
- type RequestIDMaker
- type Router
- func (mr *Router) Delete(path string, handleFunc HandleFunc)
- func (mr *Router) Get(path string, handleFunc HandleFunc)
- func (mr *Router) Handle(method, path string, handleFunc HandleFunc)
- func (mr *Router) MiddlewareHandle(method, path string, handleFunc HandleFunc, middlewares []Middleware)
- func (mr *Router) Patch(path string, handleFunc HandleFunc)
- func (mr *Router) Post(path string, handleFunc HandleFunc)
- func (mr *Router) Put(path string, handleFunc HandleFunc)
- func (mr *Router) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (mr *Router) SignalShutdown()
- func (mr *Router) With(middleware Middleware, middlewares ...Middleware) *withMiddleware
- type ShutdownChannel
- type State
Constants ¶
const StateKey = keyType(0)
StateKey is a key to stores and retrieves the State from the request context.
Variables ¶
var ErrJSONDecoding = errors.New("mux: error decodes JSON")
ErrJSONDecoding is an error when decoding JSON
Functions ¶
func FromJSON ¶
FromJSON reads JSON-encoded data from the request body and stores it in the value pointed to by v
func IsShutdownError ¶
IsShutdownError returns true if the error is a shutdown error.
func NewShutdownError ¶
NewShutdownError creates a new shutdown error with message.
Types ¶
type HandleFunc ¶
type HandleFunc func(w http.ResponseWriter, r *http.Request) error
HandleFunc is just a http.HandleFunc that can returns an error. By returning an error, now we can make a centralized error handling.
type Middleware ¶
type Middleware func(handleFunc HandleFunc) HandleFunc
Middleware is a function that will be executed before or/and after the given handleFunc has been executed.
There are two types of middleware in this Router. First is the Global middlewares and the second is the Route middlewares. The Global middlewares will be applied to all handleFunc, meanwhile the Route middlewares only applied specific to the handleFunc in the given route.
type Params ¶
type Params struct {
// contains filtered or unexported fields
}
Params is a Param-slice, as returned by the router. The slice is ordered, the first URL parameter is also the first slice value. It is therefore safe to read values by the index.
type RequestIDMaker ¶
type RequestIDMaker interface { // NextRequestID returns a unique ID for the request. NextRequestID() string }
RequestIDMaker knows how to generate a unique ID for each request. The generated request ID will be stored in the request state.
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router is an HTTP request multiplexer. It matches the URL of each incoming request against a list of registered patterns and calls the handler for the pattern that most closely matches the URL.
This router wraps the https://github.com/julienschmidt/httprouter.
func NewRouter ¶
func NewRouter(requestIDMaker RequestIDMaker, sc ShutdownChannel, middlewares ...Middleware) *Router
NewRouter creates a new mux router.
func (*Router) Delete ¶
func (mr *Router) Delete(path string, handleFunc HandleFunc)
Delete is the syntactic sugar for Handle("DELETE", path, handleFunc)
func (*Router) Get ¶
func (mr *Router) Get(path string, handleFunc HandleFunc)
Get is the syntactic sugar for Handle("GET", path, handleFunc)
func (*Router) Handle ¶
func (mr *Router) Handle(method, path string, handleFunc HandleFunc)
Handle registers the handleFunc for the given HTTP method and URL path.
func (*Router) MiddlewareHandle ¶
func (mr *Router) MiddlewareHandle(method, path string, handleFunc HandleFunc, middlewares []Middleware)
MiddlewareHandle registers the handleFunc with the Route middlewares for the given HTTP method and URL path.
func (*Router) Patch ¶
func (mr *Router) Patch(path string, handleFunc HandleFunc)
Patch is the syntactic sugar for Handle("PATCH", path, handleFunc)
func (*Router) Post ¶
func (mr *Router) Post(path string, handleFunc HandleFunc)
Post is the syntactic sugar for Handle("POST", path, handleFunc)
func (*Router) Put ¶
func (mr *Router) Put(path string, handleFunc HandleFunc)
Put is the syntactic sugar for Handle("PUT", path, handleFunc)
func (*Router) ServeHTTP ¶
func (mr *Router) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements the http.Handler interface.
func (*Router) SignalShutdown ¶
func (mr *Router) SignalShutdown()
SignalShutdown sends a shutdown signal through the shutdown channel.
func (*Router) With ¶
func (mr *Router) With(middleware Middleware, middlewares ...Middleware) *withMiddleware
With is a helper method to make Handle with middleware at the route level more easier to read. For example:
Without using With the Handle method looks like this:
router.MiddlewareHandle("GET", "/some-path", handleFunc, m1, m2, m3,..., mk)
By using With it will look like this:
router.With(m1, m2, m3, ..., mk).Handle("GET", "/some-path", handleFunc)
type ShutdownChannel ¶
ShutdownChannel is a channel that Mux used to tell the application to shutdown gracefully by sending a termination signal (syscall.SIGTERM).