You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.6 KiB

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