denco

package
v0.28.0 Latest Latest
Warning

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

Go to latest
Published: Mar 9, 2024 License: Apache-2.0, MIT Imports: 5 Imported by: 106

README

Denco Build Status

The fast and flexible HTTP request router for Go.

Denco is based on Double-Array implementation of Kocha-urlrouter. However, Denco is optimized and some features added.

Features

Installation

go get -u github.com/go-openapi/runtime/middleware/denco

Using as HTTP request multiplexer

package main

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

    "github.com/go-openapi/runtime/middleware/denco"
)

func Index(w http.ResponseWriter, r *http.Request, params denco.Params) {
    fmt.Fprintf(w, "Welcome to Denco!\n")
}

func User(w http.ResponseWriter, r *http.Request, params denco.Params) {
    fmt.Fprintf(w, "Hello %s!\n", params.Get("name"))
}

func main() {
    mux := denco.NewMux()
    handler, err := mux.Build([]denco.Handler{
        mux.GET("/", Index),
        mux.GET("/user/:name", User),
        mux.POST("/user/:name", User),
    })
    if err != nil {
        panic(err)
    }
    log.Fatal(http.ListenAndServe(":8080", handler))
}

Using as URL router

package main

import (
	"fmt"

	"github.com/go-openapi/runtime/middleware/denco"
)

type route struct {
	name string
}

func main() {
	router := denco.New()
	router.Build([]denco.Record{
		{"/", &route{"root"}},
		{"/user/:id", &route{"user"}},
		{"/user/:name/:id", &route{"username"}},
		{"/static/*filepath", &route{"static"}},
	})

	data, params, found := router.Lookup("/")
	// print `&main.route{name:"root"}, denco.Params(nil), true`.
	fmt.Printf("%#v, %#v, %#v\n", data, params, found)

	data, params, found = router.Lookup("/user/hoge")
	// print `&main.route{name:"user"}, denco.Params{denco.Param{Name:"id", Value:"hoge"}}, true`.
	fmt.Printf("%#v, %#v, %#v\n", data, params, found)

	data, params, found = router.Lookup("/user/hoge/7")
	// print `&main.route{name:"username"}, denco.Params{denco.Param{Name:"name", Value:"hoge"}, denco.Param{Name:"id", Value:"7"}}, true`.
	fmt.Printf("%#v, %#v, %#v\n", data, params, found)

	data, params, found = router.Lookup("/static/path/to/file")
	// print `&main.route{name:"static"}, denco.Params{denco.Param{Name:"filepath", Value:"path/to/file"}}, true`.
	fmt.Printf("%#v, %#v, %#v\n", data, params, found)
}

See Godoc for more details.

Getting the value of path parameter

You can get the value of path parameter by 2 ways.

  1. Using denco.Params.Get method
  2. Find by loop
package main

import (
    "fmt"

    "github.com/go-openapi/runtime/middleware/denco"
)

func main() {
    router := denco.New()
    if err := router.Build([]denco.Record{
        {"/user/:name/:id", "route1"},
    }); err != nil {
        panic(err)
    }

    // 1. Using denco.Params.Get method.
    _, params, _ := router.Lookup("/user/alice/1")
    name := params.Get("name")
    if name != "" {
        fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
    }

    // 2. Find by loop.
    for _, param := range params {
        if param.Name == "name" {
            fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
        }
    }
}

URL patterns

Denco's route matching strategy is "most nearly matching".

When routes /:name and /alice have been built, URI /alice matches the route /alice, not /:name. Because URI /alice is more match with the route /alice than /:name.

For more example, when routes below have been built:

/user/alice
/user/:name
/user/:name/:id
/user/alice/:id
/user/:id/bob

Routes matching are:

/user/alice      => "/user/alice" (no match with "/user/:name")
/user/bob        => "/user/:name"
/user/naoina/1   => "/user/:name/1"
/user/alice/1    => "/user/alice/:id" (no match with "/user/:name/:id")
/user/1/bob      => "/user/:id/bob"   (no match with "/user/:name/:id")
/user/alice/bob  => "/user/alice/:id" (no match with "/user/:name/:id" and "/user/:id/bob")

Limitation

Denco has some limitations below.

  • Number of param records (such as /:name) must be less than 2^22
  • Number of elements of internal slice must be less than 2^22

Benchmarks

cd $GOPATH/github.com/go-openapi/runtime/middleware/denco
go test -bench . -benchmem

License

Denco is licensed under the MIT License.

Documentation

Overview

Package denco provides fast URL router.

Index

Constants

View Source
const (
	// ParamCharacter is a special character for path parameter.
	ParamCharacter = ':'

	// WildcardCharacter is a special character for wildcard path parameter.
	WildcardCharacter = '*'

	// TerminationCharacter is a special character for end of path.
	TerminationCharacter = '#'

	// SeparatorCharacter separates path segments.
	SeparatorCharacter = '/'

	// PathParamCharacter indicates a RESTCONF path param
	PathParamCharacter = '='

	// MaxSize is max size of records and internal slice.
	MaxSize = (1 << 22) - 1
)

Variables

View Source
var NotFound = func(w http.ResponseWriter, r *http.Request, _ Params) {
	http.NotFound(w, r)
}

NotFound replies to the request with an HTTP 404 not found error. NotFound is called when unknown HTTP method or a handler not found. If you want to use the your own NotFound handler, please overwrite this variable.

Functions

func NextSeparator

func NextSeparator(path string, start int) int

NextSeparator returns an index of next separator in path.

Types

type Handler

type Handler struct {
	// Method is an HTTP method.
	Method string

	// Path is a routing path for handler.
	Path string

	// Func is a function of handler of HTTP request.
	Func HandlerFunc
}

Handler represents a handler of HTTP request.

type HandlerFunc

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

The HandlerFunc type is aliased to type of handler function.

type Mux

type Mux struct{}

Mux represents a multiplexer for HTTP request.

func NewMux

func NewMux() *Mux

NewMux returns a new Mux.

func (*Mux) Build

func (m *Mux) Build(handlers []Handler) (http.Handler, error)

Build builds a http.Handler.

func (*Mux) GET

func (m *Mux) GET(path string, handler HandlerFunc) Handler

GET is shorthand of Mux.Handler("GET", path, handler).

func (*Mux) HEAD

func (m *Mux) HEAD(path string, handler HandlerFunc) Handler

HEAD is shorthand of Mux.Handler("HEAD", path, handler).

func (*Mux) Handler

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

Handler returns a handler for HTTP method.

func (*Mux) POST

func (m *Mux) POST(path string, handler HandlerFunc) Handler

POST is shorthand of Mux.Handler("POST", path, handler).

func (*Mux) PUT

func (m *Mux) PUT(path string, handler HandlerFunc) Handler

PUT is shorthand of Mux.Handler("PUT", path, handler).

type Param

type Param struct {
	Name  string
	Value string
}

Param represents name and value of path parameter.

type Params

type Params []Param

Params represents the name and value of path parameters.

func (Params) Get

func (ps Params) Get(name string) string

Get gets the first value associated with the given name. If there are no values associated with the key, Get returns "".

type Record

type Record struct {
	// Key for router construction.
	Key string

	// Result value for Key.
	Value interface{}
}

Record represents a record data for router construction.

func NewRecord

func NewRecord(key string, value interface{}) Record

NewRecord returns a new Record.

type Router

type Router struct {

	// SizeHint expects the maximum number of path parameters in records to Build.
	// SizeHint will be used to determine the capacity of the memory to allocate.
	// By default, SizeHint will be determined from given records to Build.
	SizeHint int
	// contains filtered or unexported fields
}

Router represents a URL router.

func New

func New() *Router

New returns a new Router.

func (*Router) Build

func (rt *Router) Build(records []Record) error

Build builds URL router from records.

func (*Router) Lookup

func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool)

Lookup returns data and path parameters that associated with path. params is a slice of the Param that arranged in the order in which parameters appeared. e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}].

Jump to

Keyboard shortcuts

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