router.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. package echo
  2. type (
  3. // Router is the registry of all registered routes for an `Echo` instance for
  4. // request matching and URL path parameter parsing.
  5. Router struct {
  6. tree *node
  7. routes map[string]*Route
  8. echo *Echo
  9. }
  10. node struct {
  11. kind kind
  12. label byte
  13. prefix string
  14. parent *node
  15. children children
  16. ppath string
  17. pnames []string
  18. methodHandler *methodHandler
  19. }
  20. kind uint8
  21. children []*node
  22. methodHandler struct {
  23. connect HandlerFunc
  24. delete HandlerFunc
  25. get HandlerFunc
  26. head HandlerFunc
  27. options HandlerFunc
  28. patch HandlerFunc
  29. post HandlerFunc
  30. propfind HandlerFunc
  31. put HandlerFunc
  32. trace HandlerFunc
  33. }
  34. )
  35. const (
  36. skind kind = iota
  37. pkind
  38. akind
  39. )
  40. // NewRouter returns a new Router instance.
  41. func NewRouter(e *Echo) *Router {
  42. return &Router{
  43. tree: &node{
  44. methodHandler: new(methodHandler),
  45. },
  46. routes: map[string]*Route{},
  47. echo: e,
  48. }
  49. }
  50. // Add registers a new route for method and path with matching handler.
  51. func (r *Router) Add(method, path string, h HandlerFunc) {
  52. // Validate path
  53. if path == "" {
  54. panic("echo: path cannot be empty")
  55. }
  56. if path[0] != '/' {
  57. path = "/" + path
  58. }
  59. pnames := []string{} // Param names
  60. ppath := path // Pristine path
  61. for i, l := 0, len(path); i < l; i++ {
  62. if path[i] == ':' {
  63. j := i + 1
  64. r.insert(method, path[:i], nil, skind, "", nil)
  65. for ; i < l && path[i] != '/'; i++ {
  66. }
  67. pnames = append(pnames, path[j:i])
  68. path = path[:j] + path[i:]
  69. i, l = j, len(path)
  70. if i == l {
  71. r.insert(method, path[:i], h, pkind, ppath, pnames)
  72. return
  73. }
  74. r.insert(method, path[:i], nil, pkind, ppath, pnames)
  75. } else if path[i] == '*' {
  76. r.insert(method, path[:i], nil, skind, "", nil)
  77. pnames = append(pnames, "*")
  78. r.insert(method, path[:i+1], h, akind, ppath, pnames)
  79. return
  80. }
  81. }
  82. r.insert(method, path, h, skind, ppath, pnames)
  83. }
  84. func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string, pnames []string) {
  85. // Adjust max param
  86. l := len(pnames)
  87. if *r.echo.maxParam < l {
  88. *r.echo.maxParam = l
  89. }
  90. cn := r.tree // Current node as root
  91. if cn == nil {
  92. panic("echo: invalid method")
  93. }
  94. search := path
  95. for {
  96. sl := len(search)
  97. pl := len(cn.prefix)
  98. l := 0
  99. // LCP
  100. max := pl
  101. if sl < max {
  102. max = sl
  103. }
  104. for ; l < max && search[l] == cn.prefix[l]; l++ {
  105. }
  106. if l == 0 {
  107. // At root node
  108. cn.label = search[0]
  109. cn.prefix = search
  110. if h != nil {
  111. cn.kind = t
  112. cn.addHandler(method, h)
  113. cn.ppath = ppath
  114. cn.pnames = pnames
  115. }
  116. } else if l < pl {
  117. // Split node
  118. n := newNode(cn.kind, cn.prefix[l:], cn, cn.children, cn.methodHandler, cn.ppath, cn.pnames)
  119. // Reset parent node
  120. cn.kind = skind
  121. cn.label = cn.prefix[0]
  122. cn.prefix = cn.prefix[:l]
  123. cn.children = nil
  124. cn.methodHandler = new(methodHandler)
  125. cn.ppath = ""
  126. cn.pnames = nil
  127. cn.addChild(n)
  128. if l == sl {
  129. // At parent node
  130. cn.kind = t
  131. cn.addHandler(method, h)
  132. cn.ppath = ppath
  133. cn.pnames = pnames
  134. } else {
  135. // Create child node
  136. n = newNode(t, search[l:], cn, nil, new(methodHandler), ppath, pnames)
  137. n.addHandler(method, h)
  138. cn.addChild(n)
  139. }
  140. } else if l < sl {
  141. search = search[l:]
  142. c := cn.findChildWithLabel(search[0])
  143. if c != nil {
  144. // Go deeper
  145. cn = c
  146. continue
  147. }
  148. // Create child node
  149. n := newNode(t, search, cn, nil, new(methodHandler), ppath, pnames)
  150. n.addHandler(method, h)
  151. cn.addChild(n)
  152. } else {
  153. // Node already exists
  154. if h != nil {
  155. cn.addHandler(method, h)
  156. cn.ppath = ppath
  157. if len(cn.pnames) == 0 { // Issue #729
  158. cn.pnames = pnames
  159. }
  160. }
  161. }
  162. return
  163. }
  164. }
  165. func newNode(t kind, pre string, p *node, c children, mh *methodHandler, ppath string, pnames []string) *node {
  166. return &node{
  167. kind: t,
  168. label: pre[0],
  169. prefix: pre,
  170. parent: p,
  171. children: c,
  172. ppath: ppath,
  173. pnames: pnames,
  174. methodHandler: mh,
  175. }
  176. }
  177. func (n *node) addChild(c *node) {
  178. n.children = append(n.children, c)
  179. }
  180. func (n *node) findChild(l byte, t kind) *node {
  181. for _, c := range n.children {
  182. if c.label == l && c.kind == t {
  183. return c
  184. }
  185. }
  186. return nil
  187. }
  188. func (n *node) findChildWithLabel(l byte) *node {
  189. for _, c := range n.children {
  190. if c.label == l {
  191. return c
  192. }
  193. }
  194. return nil
  195. }
  196. func (n *node) findChildByKind(t kind) *node {
  197. for _, c := range n.children {
  198. if c.kind == t {
  199. return c
  200. }
  201. }
  202. return nil
  203. }
  204. func (n *node) addHandler(method string, h HandlerFunc) {
  205. switch method {
  206. case CONNECT:
  207. n.methodHandler.connect = h
  208. case DELETE:
  209. n.methodHandler.delete = h
  210. case GET:
  211. n.methodHandler.get = h
  212. case HEAD:
  213. n.methodHandler.head = h
  214. case OPTIONS:
  215. n.methodHandler.options = h
  216. case PATCH:
  217. n.methodHandler.patch = h
  218. case POST:
  219. n.methodHandler.post = h
  220. case PROPFIND:
  221. n.methodHandler.propfind = h
  222. case PUT:
  223. n.methodHandler.put = h
  224. case TRACE:
  225. n.methodHandler.trace = h
  226. }
  227. }
  228. func (n *node) findHandler(method string) HandlerFunc {
  229. switch method {
  230. case CONNECT:
  231. return n.methodHandler.connect
  232. case DELETE:
  233. return n.methodHandler.delete
  234. case GET:
  235. return n.methodHandler.get
  236. case HEAD:
  237. return n.methodHandler.head
  238. case OPTIONS:
  239. return n.methodHandler.options
  240. case PATCH:
  241. return n.methodHandler.patch
  242. case POST:
  243. return n.methodHandler.post
  244. case PROPFIND:
  245. return n.methodHandler.propfind
  246. case PUT:
  247. return n.methodHandler.put
  248. case TRACE:
  249. return n.methodHandler.trace
  250. default:
  251. return nil
  252. }
  253. }
  254. func (n *node) checkMethodNotAllowed() HandlerFunc {
  255. for _, m := range methods {
  256. if h := n.findHandler(m); h != nil {
  257. return MethodNotAllowedHandler
  258. }
  259. }
  260. return NotFoundHandler
  261. }
  262. // Find lookup a handler registered for method and path. It also parses URL for path
  263. // parameters and load them into context.
  264. //
  265. // For performance:
  266. //
  267. // - Get context from `Echo#AcquireContext()`
  268. // - Reset it `Context#Reset()`
  269. // - Return it `Echo#ReleaseContext()`.
  270. func (r *Router) Find(method, path string, c Context) {
  271. ctx := c.(*context)
  272. ctx.path = path
  273. cn := r.tree // Current node as root
  274. var (
  275. search = path
  276. child *node // Child node
  277. n int // Param counter
  278. nk kind // Next kind
  279. nn *node // Next node
  280. ns string // Next search
  281. pvalues = ctx.pvalues // Use the internal slice so the interface can keep the illusion of a dynamic slice
  282. )
  283. // Search order static > param > any
  284. for {
  285. if search == "" {
  286. goto End
  287. }
  288. pl := 0 // Prefix length
  289. l := 0 // LCP length
  290. if cn.label != ':' {
  291. sl := len(search)
  292. pl = len(cn.prefix)
  293. // LCP
  294. max := pl
  295. if sl < max {
  296. max = sl
  297. }
  298. for ; l < max && search[l] == cn.prefix[l]; l++ {
  299. }
  300. }
  301. if l == pl {
  302. // Continue search
  303. search = search[l:]
  304. } else {
  305. cn = nn
  306. search = ns
  307. if nk == pkind {
  308. goto Param
  309. } else if nk == akind {
  310. goto Any
  311. }
  312. // Not found
  313. return
  314. }
  315. if search == "" {
  316. goto End
  317. }
  318. // Static node
  319. if child = cn.findChild(search[0], skind); child != nil {
  320. // Save next
  321. if cn.prefix[len(cn.prefix)-1] == '/' { // Issue #623
  322. nk = pkind
  323. nn = cn
  324. ns = search
  325. }
  326. cn = child
  327. continue
  328. }
  329. // Param node
  330. Param:
  331. if child = cn.findChildByKind(pkind); child != nil {
  332. // Issue #378
  333. if len(pvalues) == n {
  334. continue
  335. }
  336. // Save next
  337. if cn.prefix[len(cn.prefix)-1] == '/' { // Issue #623
  338. nk = akind
  339. nn = cn
  340. ns = search
  341. }
  342. cn = child
  343. i, l := 0, len(search)
  344. for ; i < l && search[i] != '/'; i++ {
  345. }
  346. pvalues[n] = search[:i]
  347. n++
  348. search = search[i:]
  349. continue
  350. }
  351. // Any node
  352. Any:
  353. if cn = cn.findChildByKind(akind); cn == nil {
  354. if nn != nil {
  355. cn = nn
  356. nn = cn.parent // Next (Issue #954)
  357. search = ns
  358. if nk == pkind {
  359. goto Param
  360. } else if nk == akind {
  361. goto Any
  362. }
  363. }
  364. // Not found
  365. return
  366. }
  367. pvalues[len(cn.pnames)-1] = search
  368. goto End
  369. }
  370. End:
  371. ctx.handler = cn.findHandler(method)
  372. ctx.path = cn.ppath
  373. ctx.pnames = cn.pnames
  374. // NOTE: Slow zone...
  375. if ctx.handler == nil {
  376. ctx.handler = cn.checkMethodNotAllowed()
  377. // Dig further for any, might have an empty value for *, e.g.
  378. // serving a directory. Issue #207.
  379. if cn = cn.findChildByKind(akind); cn == nil {
  380. return
  381. }
  382. if h := cn.findHandler(method); h != nil {
  383. ctx.handler = h
  384. } else {
  385. ctx.handler = cn.checkMethodNotAllowed()
  386. }
  387. ctx.path = cn.ppath
  388. ctx.pnames = cn.pnames
  389. pvalues[len(cn.pnames)-1] = ""
  390. }
  391. return
  392. }