mux

package module
v0.0.0-...-6660b4b Latest Latest
Warning

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

Go to latest
Published: Aug 7, 2017 License: Apache-2.0 Imports: 6 Imported by: 4

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

Jump to

Keyboard shortcuts

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