1# Denco [](https://travis-ci.org/naoina/denco)
2
3The fast and flexible HTTP request router for [Go](http://golang.org).
4
5Denco is based on Double-Array implementation of [Kocha-urlrouter](https://github.com/naoina/kocha-urlrouter).
6However, Denco is optimized and some features added.
7
8## Features
9
10* Fast (See [go-http-routing-benchmark](https://github.com/naoina/go-http-routing-benchmark))
11* [URL patterns](#url-patterns) (`/foo/:bar` and `/foo/*wildcard`)
12* Small (but enough) URL router API
13* HTTP request multiplexer like `http.ServeMux`
14
15## Installation
16
17 go get -u github.com/go-openapi/runtime/middleware/denco
18
19## Using as HTTP request multiplexer
20
21```go
22package main
23
24import (
25 "fmt"
26 "log"
27 "net/http"
28
29 "github.com/go-openapi/runtime/middleware/denco"
30)
31
32func Index(w http.ResponseWriter, r *http.Request, params denco.Params) {
33 fmt.Fprintf(w, "Welcome to Denco!\n")
34}
35
36func User(w http.ResponseWriter, r *http.Request, params denco.Params) {
37 fmt.Fprintf(w, "Hello %s!\n", params.Get("name"))
38}
39
40func main() {
41 mux := denco.NewMux()
42 handler, err := mux.Build([]denco.Handler{
43 mux.GET("/", Index),
44 mux.GET("/user/:name", User),
45 mux.POST("/user/:name", User),
46 })
47 if err != nil {
48 panic(err)
49 }
50 log.Fatal(http.ListenAndServe(":8080", handler))
51}
52```
53
54## Using as URL router
55
56```go
57package main
58
59import (
60 "fmt"
61
62 "github.com/go-openapi/runtime/middleware/denco"
63)
64
65type route struct {
66 name string
67}
68
69func main() {
70 router := denco.New()
71 router.Build([]denco.Record{
72 {"/", &route{"root"}},
73 {"/user/:id", &route{"user"}},
74 {"/user/:name/:id", &route{"username"}},
75 {"/static/*filepath", &route{"static"}},
76 })
77
78 data, params, found := router.Lookup("/")
79 // print `&main.route{name:"root"}, denco.Params(nil), true`.
80 fmt.Printf("%#v, %#v, %#v\n", data, params, found)
81
82 data, params, found = router.Lookup("/user/hoge")
83 // print `&main.route{name:"user"}, denco.Params{denco.Param{Name:"id", Value:"hoge"}}, true`.
84 fmt.Printf("%#v, %#v, %#v\n", data, params, found)
85
86 data, params, found = router.Lookup("/user/hoge/7")
87 // print `&main.route{name:"username"}, denco.Params{denco.Param{Name:"name", Value:"hoge"}, denco.Param{Name:"id", Value:"7"}}, true`.
88 fmt.Printf("%#v, %#v, %#v\n", data, params, found)
89
90 data, params, found = router.Lookup("/static/path/to/file")
91 // print `&main.route{name:"static"}, denco.Params{denco.Param{Name:"filepath", Value:"path/to/file"}}, true`.
92 fmt.Printf("%#v, %#v, %#v\n", data, params, found)
93}
94```
95
96See [Godoc](http://godoc.org/github.com/go-openapi/runtime/middleware/denco) for more details.
97
98## Getting the value of path parameter
99
100You can get the value of path parameter by 2 ways.
101
1021. Using [`denco.Params.Get`](http://godoc.org/github.com/go-openapi/runtime/middleware/denco#Params.Get) method
1032. Find by loop
104
105```go
106package main
107
108import (
109 "fmt"
110
111 "github.com/go-openapi/runtime/middleware/denco"
112)
113
114func main() {
115 router := denco.New()
116 if err := router.Build([]denco.Record{
117 {"/user/:name/:id", "route1"},
118 }); err != nil {
119 panic(err)
120 }
121
122 // 1. Using denco.Params.Get method.
123 _, params, _ := router.Lookup("/user/alice/1")
124 name := params.Get("name")
125 if name != "" {
126 fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
127 }
128
129 // 2. Find by loop.
130 for _, param := range params {
131 if param.Name == "name" {
132 fmt.Printf("Hello %s.\n", name) // prints "Hello alice.".
133 }
134 }
135}
136```
137
138## URL patterns
139
140Denco's route matching strategy is "most nearly matching".
141
142When routes `/:name` and `/alice` have been built, URI `/alice` matches the route `/alice`, not `/:name`.
143Because URI `/alice` is more match with the route `/alice` than `/:name`.
144
145For more example, when routes below have been built:
146
147```
148/user/alice
149/user/:name
150/user/:name/:id
151/user/alice/:id
152/user/:id/bob
153```
154
155Routes matching are:
156
157```
158/user/alice => "/user/alice" (no match with "/user/:name")
159/user/bob => "/user/:name"
160/user/naoina/1 => "/user/:name/1"
161/user/alice/1 => "/user/alice/:id" (no match with "/user/:name/:id")
162/user/1/bob => "/user/:id/bob" (no match with "/user/:name/:id")
163/user/alice/bob => "/user/alice/:id" (no match with "/user/:name/:id" and "/user/:id/bob")
164```
165
166## Limitation
167
168Denco has some limitations below.
169
170* Number of param records (such as `/:name`) must be less than 2^22
171* Number of elements of internal slice must be less than 2^22
172
173## Benchmarks
174
175 cd $GOPATH/github.com/go-openapi/runtime/middleware/denco
176 go test -bench . -benchmem
177
178## License
179
180Denco is licensed under the MIT License.
View as plain text