mux

package module
v0.0.0-...-f450885 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 17, 2017 License: MIT Imports: 5 Imported by: 0

README

mux : powerful router, with first-class middleware chains.

Overview GoDoc Build Status

gomiddlware/mux aims to provide a neat interface for a mux with middleware included as first-class functions as well as endpoint handlers. Middleware and handlers are the two primary ways to compose powerful response mechanisms to any web request using your mux. Instead of using a separate library for chaining your middleware or having many intermediate variables and chaining them, just use the functions you want wherever you want.

The features that mux boasts are all idomatic Go, such as:

  • using the standard context package
  • middleware defined as func(http.Handler) http.Handler
  • handlers defined as http.Handler or http.HandlerFunc
  • no external dependencies, just plain net/http
  • everything is explicit - and is very much considered a feature (see below for the things left out)

Instead of focussing on pure-speed using a trie based router implementations, gomiddleware/mux instead focuses on being both small yet powerful. Some of the main features of mux are features that have been left out, such as:

  • no sub-routers or mouting other routers
  • no automatic case-folding on paths
  • no automatic slash/non-slash redirection
  • no adding router values into things like r.URL (uses context instead)

The combination of just middleware and handlers these two things give you a very powerful composition system where you compose middleware on prefixes and middleware chains on endpoints.

Installation

go get github.com/gomiddleware/mux

Usage / Example

// new Mux
m := mux.New()

// log every request
m.Use("/", logger.New())

// serve a static set of files under "/s/"
m.All("/s", http.FileServer(http.Dir("./static")))

// every (non-static) request gets a 'X-Request-ID' request header
m.Use("/", reqid.RandomId)

// serve the /about page
m.Get("/about", aboutHandler)

// serve home, with one middleware specific to it's route
m.Get("/", incHomeHits, homeHandler)

// now check if adding any of the routes failed
if m.Err != nil {
    log.Fatal(m.Err)
}

// start the server
http.ListenAndServe(":8080", m)

Author

By Andrew Chilton, @twitter.

For AppsAttic, @AppsAttic.

LICENSE

MIT.

Documentation

Overview

Package mux is a simple(ish) mux, however, it provides a few nice features such as easy use of middleware chains and a router which doesn't automatically look at only prefixes (like the Go built-in mux). Everything is explicit and nothing is done for you. ie. we don't automatically redirect to a slash or non-slash version of each path, you need to do that yourself (or use https://github.com/gomiddleware/slash to help).

There are two fundamentals at work here, middleware and handlers. Middleware is expected to either: (1) do something with the request/response/context on the way in, call the `next` middleware and optionally do something on the way out, or (2) deal with the request completely and not call the `next` middleware at all. It is up to the middleware to decide this.

An example of middleware calling next might be adding a requestId in to each request's Context.

An example of middleware dealing with the request might be to check that a user is logged in, and if not, sending a redirect to "/", or send back a 405.

For the purposes of this library (and in general), a middleware is defined as one of these:

• func(http.Handler) http.Handler

• func(http.HandlerFunc) http.HandlerFunc

For the purposes of this library (and in general), a handler is defined as:

• http.Handler

• func(http.ResponseWriter, *http.Request)

To add middleware to any prefix, use:

m.Use("/prefix", middlewares...)

To add a handler to any path, use one of Get/Post/Put/Patch/Delete/Options/Head such as:

m.Get("/path", [middlewares...,] handler)

Of course, you can only add one handler to each route, and it must be the last thing you pass in.

Don't worry that you are passing one of 4 types in to each method since they are organised at the time they are added, and not during the request cycle. Only type assertions are used and not reflection.

Example

m := mux.New()

m.Use("/", logger.New())

m.Get("/", func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Home\n"))
})

m.Get("/my/", checkUserIsSignedIn, userHomeHandler)

// 'postName' can be fetched with mux.Vals(r) inside `postHandler`
m.Get("/post/:postName", postHandler)

if m.Err != nil {
    // ... something went wrong with a route
}

log.Fatal(http.ListenAndServe(":8080", m))

More information and examples can be found at http://chilts.org/2017/01/27/gomiddleware-mux

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrPathMustStartWithSlash is returned when you create a route which doesn't start with a slash.
	ErrPathMustStartWithSlash = errors.New("mux: path must start with a slash")

	// ErrMultipleHandlers is returned when you create a route with multiple handlers.
	ErrMultipleHandlers = errors.New("mux: route has been given two handlers but only one can be provider")

	// ErrMiddlewareAfterHandler is returned when you create a route which has some middleware defined after the
	// handler.
	ErrMiddlewareAfterHandler = errors.New("mux: route can't have middleware defined after the handler")

	// ErrUnknownTypeInRoute is returned when something unexpected is passed to a route function.
	ErrUnknownTypeInRoute = errors.New("mux: unexpected type passed to route")
)

Errors that can be returned from this package.

Functions

func Vals

func Vals(r *http.Request) map[string]string

Vals enables you to retrieve the placeholder matches of the current request.

A placeholder can be set using a path such as "/path/:placeholder/to/" and Vals will return is in the map with the key "placeholder".

Types

type Mux

type Mux struct {
	Err error
	// contains filtered or unexported fields
}

Mux is an array of routes, prefixes, and an error (if one has happened).

func New

func New() *Mux

New returns a new initialized Mux. Nothing is automatic. You must do slash/non-slash redirection yourself.

func (*Mux) All

func (m *Mux) All(path string, things ...interface{})

All adds a handler to a path prefix for all methods. Essentially a catch-all. Unlike other methods such as Get, Post, Put, Patch, and Delete, All matches for the prefix only and not the entire path.

e.g. m.All("/s", ...) matches the requests "/s/img.png", "/s/css/styles.css", and "/s/js/app.js".

func (*Mux) Delete

func (m *Mux) Delete(path string, things ...interface{})

Delete is a shortcut for mux.add("DELETE", path, things...)

func (*Mux) Get

func (m *Mux) Get(path string, things ...interface{})

Get is a shortcut for mux.add("GET", path, things...)

func (*Mux) Head

func (m *Mux) Head(path string, things ...interface{})

Head is a shortcut for mux.add("HEAD", path, things...)

func (*Mux) Options

func (m *Mux) Options(path string, things ...interface{})

Options is a shortcut for mux.add("OPTIONS", path, things...)

func (*Mux) Patch

func (m *Mux) Patch(path string, things ...interface{})

Patch is a shortcut for mux.add("PATCH", path, things...)

func (*Mux) Post

func (m *Mux) Post(path string, things ...interface{})

Post is a shortcut for mux.add("POST", path, things...)

func (*Mux) Put

func (m *Mux) Put(path string, things ...interface{})

Put is a shortcut for mux.add("PUT", path, things...)

func (*Mux) ServeHTTP

func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP makes the router implement the http.Handler interface.

func (*Mux) Use

func (m *Mux) Use(path string, things ...interface{})

Use adds some middleware to a path prefix. Unlike other methods such as Get, Post, Put, Patch, and Delete, Use matches for the prefix only and not the entire path. (Though of course, the entire exact path also matches.)

e.g. m.Use("/profile/", ...) matches the requests "/profile/", "/profile/settings", and "/profile/a/path/to/".

Note however, m.Use("/profile/", ...) doesn't match "/profile" since it contains too many slashes. But m.Use("/profile", ...) does match "/profile/" and "/profile/..." (but check that's actually what you want here).

type Prefix

type Prefix struct {
	Path        string
	Segments    []string
	Length      int
	Middlewares []func(http.Handler) http.Handler
	Handler     http.Handler
}

Prefix is an internal "path + middlewares" type created when each middleware prefix is added. When adding we'll add the middlewares to the array of Middlewares.

type Route

type Route struct {
	Method      string
	Path        string
	Segments    []string
	Length      int
	Middlewares []func(http.Handler) http.Handler
	Handler     http.Handler
}

Route is an internal "method + path + middlewares + handler" type created when each route is added. When adding a handler for Get(), Post(), Put(), Delete(), Options(), and Patch(), the middlewares prior to this route (and any on this route) are combined to create the final handler.

These are not computed during routing but when added to the router, therefore they have negligible overhead.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL