Skip to content
/ mux Public

A fast router for golang, handling static paths and dynamic complex params with deferred parsing

License

Notifications You must be signed in to change notification settings

fragmenta/mux

Repository files navigation

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


About

A fast router for golang, handling static paths and dynamic complex params with deferred parsing

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages