mux

package module
v1.6.7 Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2020 License: MIT Imports: 15 Imported by: 31

README

Fragmenta Multiplexer (mux)

Fragmenta mux is a replacement the standard http.ServeMux which offers a few additional features and improved efficiency. Features are very similar to gorilla/mux but with a few additions, and it is compatible with the standard http.Handler interface or handlers returning error.

It offers the following features:

  • Named paramaters including regexp matches for params (e.g. {id:\d+} to match id only to one or more numerals)
  • Delayed param parsing (url,query,form) with utility functions for extracting Int, Bool, Float params.
  • Routes are evaluated strictly in order - add important routes first and catch-alls at the end
  • Zero allocations when matching means low-memory use and responses as fast as httprouter for static routes
  • A cache in front of route matching speeds up responses (under 100ns/op in a simple static case)
  • Low memory usage (even with cache)
  • Accepts either the standard http.Handler interface or mux.Handler (same but with error return)
  • Add middleware http.HandlerFunc for chaining standard Go middleware for auth, logging etc.

It does not offer:

  • Nested routes or groups

Install

Perform the usual incantation:

  go get -u github.com/fragmenta/mux

Usage

Usage is as you'd expect if you've used the stdlib mux or gorilla mux. You can use the mux.Add/Get/Post to add handlers which return an error, or mux.AddHandler to add a stdlib http.HandlerFunc.


func main() {
  m := mux.New()
  m.Get(`/`,homeHandler)
  m.Get(`/users`,users.HandleIndex)
  m.Post(`/users`,users.HandleCreate)
  m.Post(`/users/{id:\d+}/update`,users.HandleUpdate)
  http.Handle("/", r)
}


Errors

Because of the handler signature returning errors, you can set an ErrorHandler which is called if an error occurs inside one of your handlers, and a FileHandler which is called for serving files if no route is found. This makes handling errors more elegant, instead of this:


if err != nil {
  log.Printf("error occured:%s",err)
  // .. do something to handle and display to user
  return 
}

you can do this in your handlers:


if err != nil {
  return err
}

and display errors in a consistent way using your ErrorHandler function (you can also return a custom error type from handlers as fragmenta does to send more information than just error).

Params

Parsing of params is delayed until you require them in your handler - no parsing is done until that point. When you do require them, just parse params as follows, and a full params object will be available with a map of all params from urls, and form bodies. Multipart file forms are parsed automatically and the files made available for use.


// Parse  params (any url, query and form params)
params,err := mux.Params(request)
if err != nil {
  return err
}

params.Values["key"][4]
params.Get("my_query_key")
params.GetInt("user_id")
params.GetFloat("float")
params.GetBool("bool")
params.GetDate("published_at","2017-01-02")

for _,fh := range params.Files {
  
}

Benchmarks

Speed isn't everything (see the list of features above), but it is important the router doesn't slow down request times, particularly if you have a lot of urls to match. For benchmarks against a few popular routers, see https://github.com/kennygrant/routebench

Performance is adequate:


BenchmarkStatic/stdlib_mux-4         	    1000	   1946545 ns/op	   20619 B/op	     537 allocs/op
BenchmarkStatic/gorilla_mux-4        	    1000	   1846382 ns/op	  115648 B/op	    1578 allocs/op
BenchmarkStatic/fragmenta_mux-4      	  100000	     13969 ns/op	       0 B/op	       0 allocs/op
BenchmarkStatic/httprouter_mux-4     	  100000	     16240 ns/op	       0 B/op	       0 allocs/op

BenchmarkGithubFuzz/stdlib_mux-4               	     300	   4592686 ns/op	   35767 B/op	     902 allocs/op
BenchmarkGithubFuzz/gorilla_mux-4              	     100	  12931693 ns/op	  246784 B/op	    2590 allocs/op
BenchmarkGithubFuzz/fragmenta_mux-4            	    5000	    324911 ns/op	    7617 B/op	     136 allocs/op
BenchmarkGithubFuzz/httprouter_mux-4           	   10000	    101702 ns/op	   23791 B/op	     296 allocs/op


Documentation

Index

Constants

This section is empty.

Variables

View Source
var MaxCacheEntries = 500

MaxCacheEntries defines the maximum number of entries in the request->route cache 0 means caching is turned off

Functions

func SetDefault

func SetDefault(m *Mux)

SetDefault sets the default mux on the package for use in parsing params we could instead decorate each request with a reference to the Route but this means extra allocations for each request, when almost all apps require only one mux.

Types

type ErrorHandlerFunc

type ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)

ErrorHandlerFunc defines a HandlerFunc which accepts an error and displays it.

type HandlerFunc

type HandlerFunc func(w http.ResponseWriter, r *http.Request) error

HandlerFunc defines a std net/http HandlerFunc, but which returns an error.

type Middleware

type Middleware func(http.HandlerFunc) http.HandlerFunc

Middleware is a handler that wraps another handler

type Mux

type Mux struct {

	// See httptrace for best way to instrument
	ErrorHandler ErrorHandlerFunc
	FileHandler  HandlerFunc
	RedirectWWW  bool
	// contains filtered or unexported fields
}

Mux handles http requests by selecting a handler and passing the request to it. Routes are evaluated in the order they were added. Before the request reaches the handler it is passed through the middleware chain.

func New

func New() *Mux

New returns a new mux

func (*Mux) Add

func (m *Mux) Add(pattern string, handler HandlerFunc) Route

Add adds a route for this request with the default methods (GET/HEAD) Route is returned so that method functions can be chained

func (*Mux) AddHandler

func (m *Mux) AddHandler(pattern string, handler http.HandlerFunc) Route

AddHandler adds a route for this pattern using a stdlib http.HandlerFunc which does not return an error.

func (*Mux) AddMiddleware

func (m *Mux) AddMiddleware(middleware Middleware)

AddMiddleware adds a middleware function, this should be done before starting the server as it remakes our chain of middleware. This prepends to our chain of middleware

func (*Mux) Get

func (m *Mux) Get(pattern string, handler HandlerFunc) Route

Get adds a route for this pattern/hanlder with the default methods (GET/HEAD)

func (*Mux) Match

func (m *Mux) Match(r *http.Request) Route

Match finds the route (if any) which matches this request

func (*Mux) Post

func (m *Mux) Post(pattern string, handler HandlerFunc) Route

Post adds a route for this pattern/hanlder with method http.PostMethod

func (*Mux) RouteRequest

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

RouteRequest is the final endpoint of all requests

func (*Mux) ServeHTTP

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

ServeHTTP implements net/http.Handler.

type NaiveRoute

type NaiveRoute struct {
	// contains filtered or unexported fields
}

NaiveRoute holds a pattern which matches a route and params within it, and an associated handler which will be called when the route matches.

func (*NaiveRoute) Delete

func (r *NaiveRoute) Delete() Route

Delete sets the method exclusively to DELETE

func (*NaiveRoute) Get

func (r *NaiveRoute) Get() Route

Get sets the method exclusively to GET

func (*NaiveRoute) Handle

func (r *NaiveRoute) Handle(w http.ResponseWriter, req *http.Request) error

Handle calls the handler with the writer and request.

func (*NaiveRoute) Handler

func (r *NaiveRoute) Handler() HandlerFunc

Handler returns our handlerfunc.

func (*NaiveRoute) Match

func (r *NaiveRoute) Match(path string) bool

Match returns true if this route matches the path given.

func (*NaiveRoute) MatchMaybe

func (r *NaiveRoute) MatchMaybe(path string) bool

MatchMaybe returns false if the path definitely is not MatchMethod or true/maybe if it *may* match.

func (*NaiveRoute) MatchMethod

func (r *NaiveRoute) MatchMethod(method string) bool

MatchMethod returns true if our list of methods contains method

func (*NaiveRoute) Method

func (r *NaiveRoute) Method(method string) Route

Method sets the method exclusively to method

func (*NaiveRoute) Methods

func (r *NaiveRoute) Methods(permitted ...string) Route

Methods sets the methods allowed as an array

func (*NaiveRoute) Parse

func (r *NaiveRoute) Parse(path string) map[string]string

Parse parses this path given our regexp and returns a map of URL params.

func (*NaiveRoute) Pattern

func (r *NaiveRoute) Pattern() string

Pattern returns the string pattern for the route

func (*NaiveRoute) Post

func (r *NaiveRoute) Post() Route

Post sets the method exclusively to POST

func (*NaiveRoute) Put

func (r *NaiveRoute) Put() Route

Put sets the method exclusively to PUT

func (*NaiveRoute) Setup

func (r *NaiveRoute) Setup(p string, h HandlerFunc) error

Setup sets up the route from a pattern

func (*NaiveRoute) String

func (r *NaiveRoute) String() string

String returns the route formatted as a string

type PrefixRoute

type PrefixRoute struct {
	NaiveRoute
	// contains filtered or unexported fields
}

PrefixRoute uses a static prefix to reject route matches quickly.

func (*PrefixRoute) MatchMaybe

func (r *PrefixRoute) MatchMaybe(path string) bool

MatchMaybe returns false if the path definitely is not MatchMethod or true/maybe if it *may* match.

func (*PrefixRoute) Setup

func (r *PrefixRoute) Setup(p string, h HandlerFunc) error

Setup sets up the pattern prefix for the Prefix route.

func (*PrefixRoute) String

func (r *PrefixRoute) String() string

String returns the route formatted as a string.

type RequestParams

type RequestParams struct {
	Values url.Values
	Files  map[string][]*multipart.FileHeader
}

RequestParams parses all params in a request and stores them in Values this includes: path params (from route) query params (from request) body params (from form request bodies)

func Params

func Params(r *http.Request) (*RequestParams, error)

Params returns a new set of params parsed from the request.

func ParamsJSON added in v1.6.7

func ParamsJSON(r *http.Request) (*RequestParams, error)

ParamsJSON returns a new set of params parsed from the request (json included, for testing). This is a temporary method for testing json parsing, we should add this capability to Params()

func ParamsWithMux

func ParamsWithMux(m *Mux, r *http.Request) (*RequestParams, error)

ParamsWithMux returns params for a given mux and request

func (*RequestParams) Add

func (p *RequestParams) Add(key string, values []string)

Add appends these values to this key, without removing any other entries.

func (*RequestParams) Delete

func (p *RequestParams) Delete(key string)

Delete all values associated with the key.

func (*RequestParams) Exists added in v1.6.5

func (p *RequestParams) Exists(key string) bool

Exists returns true if this key exists in Values

func (*RequestParams) Get

func (p *RequestParams) Get(key string) string

Get returns the first value for this key or a blank string if no entry.

func (*RequestParams) GetDate

func (p *RequestParams) GetDate(key string, format string) (time.Time, error)

GetDate returns the first value associated with a given key as a time,

using the given time format.

func (*RequestParams) GetFloat

func (p *RequestParams) GetFloat(key string) float64

GetFloat returns the first value associated with the key as an integer. If there is no value or a parse error, it returns 0.0

func (*RequestParams) GetFloats

func (p *RequestParams) GetFloats(key string) []float64

GetFloats returns all values associated with the key as an array of floats.

func (*RequestParams) GetInt

func (p *RequestParams) GetInt(key string) int64

GetInt returns the first value associated with the given key as an integer. If there is no value or a parse error, it returns 0 If the string contains non-numeric characters, it is truncated from the first non-numeric character.

func (*RequestParams) GetInts

func (p *RequestParams) GetInts(key string) []int64

GetInts returns all values associated with the key as an array of integers.

func (*RequestParams) GetIntsString

func (p *RequestParams) GetIntsString(key string) string

GetIntsString returns all values associated with the key as a comma separated string.

func (*RequestParams) GetStrings added in v1.6.5

func (p *RequestParams) GetStrings(key string) []string

GetStrings returns all string values associated with this key if there are no values associated an empty array is returned

func (*RequestParams) GetUniqueInts

func (p *RequestParams) GetUniqueInts(key string) []int64

GetUniqueInts returns all unique non-zero int values associated with the given key as an array of integers

func (*RequestParams) Map

func (p *RequestParams) Map() map[string]string

Map returns a flattened map of params with only one entry for each key, rather than the array of values Request params allow.

func (*RequestParams) Set

func (p *RequestParams) Set(key string, values []string)

Set sets this key to these values, removing any other entries.

func (*RequestParams) SetInt added in v1.5.5

func (p *RequestParams) SetInt(key string, v int64)

SetInt sets this key to this single string value, removing any other entries.

func (*RequestParams) SetString added in v1.5.5

func (p *RequestParams) SetString(key string, v string)

SetString sets this key to this single string value, removing any other entries.

type Route

type Route interface {
	// Match against URL
	MatchMethod(string) bool
	MatchMaybe(string) bool
	Match(string) bool

	// Handler returns the handler to execute
	Handler() HandlerFunc

	// Parse the URL for params according to pattern
	Parse(string) map[string]string

	// Set accepted methods
	Get() Route
	Post() Route
	Put() Route
	Delete() Route
	Methods(...string) Route
}

Route defines the interface routes are expected to conform to.

func NewNaiveRoute

func NewNaiveRoute(pattern string, handler HandlerFunc) (Route, error)

NewNaiveRoute creates a new Route, given a pattern to match and a handler for the route.

func NewPrefixRoute

func NewPrefixRoute(pattern string, handler HandlerFunc) (Route, error)

NewPrefixRoute creates a new PrefixRoute, given a pattern to match and a handler for the route.

func NewRoute

func NewRoute(pattern string, handler HandlerFunc) (Route, error)

NewRoute returns a new Route of our default type.

Directories

Path Synopsis
log
Package log provides logging interfaces for use in handlers and loggers for stdout, files, and time series databases
Package log provides logging interfaces for use in handlers and loggers for stdout, files, and time series databases
adapters/influx
Package influx sends values to an influxdb database
Package influx sends values to an influxdb database
middleware
gzip
Package gzip provides gzip middleware to gzip responses where appropriate
Package gzip provides gzip middleware to gzip responses where appropriate
secure
Package secure adds headers to protect against xss and reflection attacks and force use of https
Package secure adds headers to protect against xss and reflection attacks and force use of https

Jump to

Keyboard shortcuts

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