README

mux

Build Status Coverage Status GoDoc

A high performance and powerful trie based url path router for Go.

This router supports fixed and regex rules in routing pattern, and matches request method. It's optimized by trie structure for faster matching and large scale rules.

requirement: Go 1.7+

Feature

todo

Usage

This is a simple example for mux. Read godoc to get full api documentation.

There is a basic example:

package main

import (
    	"fmt"
	"log"
	"net/http"

	"github.com/beego/mux"
)

func main() {
	mx := mux.New()
	mx.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("hello, beego mux"))
	})
	mx.Get("/abc/:id", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "hello, abc page %s", mux.Param(r,":id"))
	})

	log.Fatal(http.ListenAndServe("127.0.0.1:9999", mx))
}

Register route mapping as http.HandleFunc via http method name:

mx.Get("/get", getHandleFunc)
mx.Post("/post", postHandleFunc)
mx.Put("/put", putHandleFunc)
mx.Delete("/delete", deleteHandleFunc)
mx.Head("/head", headHandleFunc)
mx.Options("/options", optionsHandleFunc)
mx.Patch("/patch", patchHandleFunc)

Or use raw api to add route with http method name:

mx.Handle("GET", "/abc", abcHandleFunc)

Register http.Handle.

mx2 := mux.New()
mx.Get("/ttt", getHandleFunc)
mx.Handler("GET","/abc", mx2) // /abc/ttt -> getHandleFunc
default handler

Register default handle to resolve missing matches. If can not find matched pattern, mux runs default handler if set.

mx.Get("/abc",abcHandleFunc)
mx.DefaultHandler(defaultHandleFunc)
// abc -> abcHandleFunc
// ^abc -> defaultHandleFunc

Routing

The routing pattern can set as fixed pattern as most simple way. When using fixed pattern, it supports to parse json, xml and html extension to match pattern.

Pattern: /abc/xyz

/abc/xyz        matched
/abc/xyz.html   matched 
/abc/xyz.json   matched 
/abc/xyz.xml    matched 
/abc/xzz        no matched

But in common cases, you need parameters to match differenct segments in path.

Named parameters

As you see, :id is a named parameter. The matched parameters can read one via mux.Param method from *http.Request by parameter's name.

// r is *http.Request
fmt.Println(mux.Param(r,":id"))

Or read all parameters by mux.Params.

// r is *http.Request
fmt.Println(mux.Params(r))
// e.g. map[:id:1 :name:beego]

A named parameter only can match single segment of path with extension.

Pattern: /abc/:id

/abc/           no match
/abc/123        matched     (:id is 123)
/abc/xyz        matched     (:id is xyz)
/abc/123/xyz    no matched
/abc/123.html   matched     (:id is 123.html)
Wildcard parameters

If you need to match several segments in path, use * and *.* named wildcard parameters.

* matches all segments between previous and next segment node in pattern. The matched segement parts are stored in params with key :splat.

Pattern: /abc/*/xyz

/abc/xyz                no match
/abc/123/xyz            matched     (:splat is 123)
/abc/12/34/xyz          matched     (:splat is 12/34)  

*.* has familar behaviour with *, but matched results are two parts, :path as path segment and :ext as extension suffix.

Pattern : /abc/*.*

/abc/xyz.json           matched     (:path is xyz, :ext is json)
/abc/123/xyz.html       matched     (:path is 123/xyz, :ext is html)
Regexp parameters

mux supports a regular expression as a paramter , named regexp paramaters. You can set a regexp into pattern with a name placeholder.

Pattern : /abc/:id([0-9]+)

/abc/123                matched     (:id is 123)
/abc/xyz                no matched

You can set value type for one named paramater to simplify some common regexp rules. Now support :int ([0-9]+) and :string ([\w]+).

Pattern: /abc/:id:int

/abc/123        matched (:id is 123)
/abc/xyz        no match

Regexp paramters can match several parts in one segment in path.

Pattern: /abc/article_:id:int

/abc/123            no matched
/abc/article_123    matched     (:id is 123)
/abc/article_xyz    no matched
Optional parameters

If the parameter can be not found in pattern when matching url, use ? to declare this situation. ? support named and regexp parameters.

Pattern: /abc/xyz/?:id

/abc/xyz/               matched     (:id is empty)
/abc/xyz/123            matched     (:id is 123)
Pattern: /abc/xyz/?:id:int

/abc/xyz/               matched     (:id is empty)
/abc/xyz/123            matched     (:id is 123)
/abc/xyz/aaa            no matched
Complex patterns

The fixed segements, named parameters and regexp patterns can be used in one rule together.

Pattern: /article/:id/comment_:page:int

/article/12/comment_2       matched     (:id is 12, :page is 2)
/article/abc/comment_3      matched     (:id is abc, :page is 3)
/article/abc/comment_xyz    no match
Pattern: /data/:year/*/list

/data/2012/11/12/list       matched     (:year is 2012, :splat is 11/12)
/data/2014/12/list          matched     (:year is 2014, :splat is 12)
Pattern: /pic/:width:int/:height:int/*.*

/pic/20/20/aaaaaa.jpg      matched     (:width is 20, :height is 20, :path is aaaaaa, :ext is jpg)
pattern matching order

Static pattern > parameters' pattern > regexp pattern.

URL : /abc/99

pattern: /abc/99            matched
pattern: /abc/:id           no match
pattern: /abc/:id:int       no match

URL : /abc/123

pattern: /abc/99            no match
pattern: /abc/:id           matched    (:id is 123)
pattern: /abc/:id:int       no match

If register confusing patterns, it matches first one in adding order. For example, in regexp patterns:

mx := mux.New()

mx.Get("/abc/?:id:int", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "abc, int params %v", mux.Params(r))
})
mx.Get("/abc/?:name:string", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "abc, string params %v", mux.Params(r))
})

mx.Get("/xyz/?:name:string", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "xyz, string params %v", mux.Params(r))
})
mx.Get("/xyz/?:id:int", func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "xyz, int params %v", mux.Params(r))
})

When using this mx to match urls, it shows result:

URL				Pattern
/abc		->		/abc/?:id:int			(first one)
/abc/123	->		/abc/?:id:int
/abc/zzz	->		/abc/?:name:string

/xyz		->		/xyz/?:name:string		(first one)
/xyz/123	->		/xyz/?:name:string		(123 is treated as string "123")
/xyz/zzz	->		/xyz/?:name:string

Documentation

Overview

    Package mux implements a high performance and powerful trie based url path router for Go.

    Index

    Constants

    View Source
    const Version = "0.0.1"

      Version holds the current mux version

      Variables

      This section is empty.

      Functions

      func Param

      func Param(r *http.Request, key string) string

        Param return the router param based on the key

        func Params

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

          Params return the router params

          Types

          type Matched

          type Matched struct {
          	// Either a Node pointer when matched or nil
          	Node *Node
          
          	// Either a map contained matched values or empty map.
          	Params map[string]string
          
          	// Matched path to access
          	// If Node is nil then redirect to this PATH
          	Path string
          }

            Matched is a result returned by Trie.Match.

            type Mux

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

              Mux is a tire base HTTP request router which can be used to dispatch requests to different handler functions.

              func New

              func New(opts ...Options) *Mux

                New returns a Mux instance.

                func (*Mux) DefaultHandler

                func (m *Mux) DefaultHandler(handler http.HandlerFunc)

                  DefaultHandler registers a new handler in the Mux that will run if there is no other handler matching.

                  func (*Mux) Delete

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

                    Delete registers a new DELETE route for a path with matching handler in the Mux.

                    func (*Mux) Get

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

                      Get registers a new GET route for a path with matching handler in the Mux.

                      func (*Mux) Handle

                      func (m *Mux) Handle(method, pattern string, handler http.HandlerFunc)

                        Handle registers a new handler with method and path in the Mux. For GET, POST, PUT, PATCH and DELETE requests the respective shortcut functions can be used.

                        func (*Mux) Handler

                        func (m *Mux) Handler(method, path string, handler http.Handler)

                          Handler is an adapter which allows the usage of an http.Handler as a request handle.

                          func (*Mux) Head

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

                            Head registers a new HEAD route for a path with matching handler in the Mux.

                            func (*Mux) Options

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

                              Options registers a new OPTIONS route for a path with matching handler in the Mux.

                              func (*Mux) Patch

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

                                Patch registers a new PATCH route for a path with matching handler in the Mux.

                                func (*Mux) Post

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

                                  Post registers a new POST route for a path with matching handler in the Mux.

                                  func (*Mux) Put

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

                                    Put registers a new PUT route for a path with matching handler in the Mux.

                                    func (*Mux) ServeHTTP

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

                                      ServeHTTP implemented http.Handler interface

                                      type Node

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

                                        Node represents a node on defined patterns that can be matched.

                                        func (*Node) BuildURL

                                        func (n *Node) BuildURL(pairs ...string) (*url.URL, error)

                                          BuildURL will builds a URL for the pattern.

                                          func (*Node) GetAllow

                                          func (n *Node) GetAllow() []string

                                            GetAllow returns allow methods defined on the node

                                            trie := New()
                                            trie.Parse("/").Handle("GET", handler1)
                                            trie.Parse("/").Handle("PUT", handler2)
                                            
                                            // trie.Match("/").Node.GetAllow() == []string{"GET", "PUT"}
                                            

                                            func (*Node) GetHandler

                                            func (n *Node) GetHandler(method string) interface{}

                                              GetHandler ... GetHandler returns handler by method that defined on the node

                                              trie := New()
                                              trie.Parse("/api").Handle("GET", func handler1() {})
                                              trie.Parse("/api").Handle("PUT", func handler2() {})
                                              
                                              trie.Match("/api").Node.GetHandler("GET").(func()) == handler1
                                              trie.Match("/api").Node.GetHandler("PUT").(func()) == handler2
                                              

                                              func (*Node) GetName

                                              func (n *Node) GetName(name string) *Node

                                                GetName returns the name for the route, if any.

                                                func (*Node) Handle

                                                func (n *Node) Handle(method string, handler interface{})

                                                  Handle is used to mount a handler with a method name to the node.

                                                  t := New()
                                                  node := t.Define("/a/b")
                                                  node.Handle("GET", handler1)
                                                  node.Handle("POST", handler1)
                                                  

                                                  func (*Node) Name

                                                  func (n *Node) Name(name string) *Node

                                                    Name sets the name for the route, used to build URLs.

                                                    type Options

                                                    type Options struct {
                                                    	// CaseSensitive when matching URL path.
                                                    	CaseSensitive bool
                                                    
                                                    	// PathClean defines the path cleaning behavior for new routes. The default value is false.
                                                    	// Users should be careful about which routes are not cleaned
                                                    	// When true, the path will be cleaned, if the route path is "/path//to", it will return "/path/to"
                                                    	// When false, if the route path is "/path//to", it will remain with the double slash
                                                    	PathClean bool
                                                    
                                                    	// 	StrictSlash defines the trailing slash behavior for new routes.
                                                    	// The initial value is false.
                                                    	// When true, if the route path is "/path/", accessing "/path" will
                                                    	//    redirect to the former and vice versa. In other words,
                                                    	//    your application will always see the path as specified in the route.
                                                    	// When false, if the route path is "/path", accessing "/path/" will
                                                    	//    not match this route and vice versa.
                                                    	StrictSlash bool
                                                    
                                                    	// UseEncodedPath tells the router to match the encoded original path to the routes.
                                                    	// For eg. "/path/foo%2Fbar/to" will match the path "/path/{var}/to".
                                                    	// This behavior has the drawback of needing to match routes against r.RequestURI instead of r.URL.Path.
                                                    	// Any modifications (such as http.StripPrefix) to r.URL.Path will not affect routing when this flag is
                                                    	// on and thus may induce unintended behavior.
                                                    	// If not called, the router will match the unencoded path to the routes.
                                                    	// For eg. "/path/foo%2Fbar/to" will match the path "/path/foo/bar/to"
                                                    	UseEncodedPath bool
                                                    }

                                                      Options describes options for Trie.

                                                      type Trie

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

                                                        Trie represents a trie that defining patterns and matching URL.

                                                        func NewTrie

                                                        func NewTrie(args ...Options) *Trie

                                                          NewTrie returns a trie

                                                          trie := New()
                                                          // disable CaseSensitive, PathClean and StrictSlash
                                                          trie := New(Options{})
                                                          

                                                          func (*Trie) Match

                                                          func (t *Trie) Match(path string) (*Matched, error)

                                                            Match try to match path. It will returns a Matched instance that includes *Node, Params when matching success, otherwise a nil.

                                                            matched, err := trie.Match("/a/b")
                                                            

                                                            func (*Trie) Parse

                                                            func (t *Trie) Parse(pattern string) *Node

                                                              Parse will parse the pattern and returns the endpoint node for the pattern.

                                                              trie := New()
                                                              node1 := trie.Parse("/a")
                                                              node2 := trie.Parse("/a/b")
                                                              node3 := trie.Parse("/a/b")
                                                              // node2.parent == node1
                                                              // node2 == node3