routergroup.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package blademaster
  2. import (
  3. "regexp"
  4. )
  5. // IRouter http router framework interface.
  6. type IRouter interface {
  7. IRoutes
  8. Group(string, ...HandlerFunc) *RouterGroup
  9. }
  10. // IRoutes http router interface.
  11. type IRoutes interface {
  12. UseFunc(...HandlerFunc) IRoutes
  13. Use(...Handler) IRoutes
  14. Handle(string, string, ...HandlerFunc) IRoutes
  15. HEAD(string, ...HandlerFunc) IRoutes
  16. GET(string, ...HandlerFunc) IRoutes
  17. POST(string, ...HandlerFunc) IRoutes
  18. PUT(string, ...HandlerFunc) IRoutes
  19. DELETE(string, ...HandlerFunc) IRoutes
  20. }
  21. // RouterGroup is used internally to configure router, a RouterGroup is associated with a prefix
  22. // and an array of handlers (middleware).
  23. type RouterGroup struct {
  24. Handlers []HandlerFunc
  25. basePath string
  26. engine *Engine
  27. root bool
  28. baseConfig *MethodConfig
  29. }
  30. var _ IRouter = &RouterGroup{}
  31. // Use adds middleware to the group, see example code in doc.
  32. func (group *RouterGroup) Use(middleware ...Handler) IRoutes {
  33. for _, m := range middleware {
  34. group.Handlers = append(group.Handlers, m.ServeHTTP)
  35. }
  36. return group.returnObj()
  37. }
  38. // UseFunc adds middleware to the group, see example code in doc.
  39. func (group *RouterGroup) UseFunc(middleware ...HandlerFunc) IRoutes {
  40. group.Handlers = append(group.Handlers, middleware...)
  41. return group.returnObj()
  42. }
  43. // Group creates a new router group. You should add all the routes that have common middlwares or the same path prefix.
  44. // For example, all the routes that use a common middlware for authorization could be grouped.
  45. func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup {
  46. return &RouterGroup{
  47. Handlers: group.combineHandlers(handlers),
  48. basePath: group.calculateAbsolutePath(relativePath),
  49. engine: group.engine,
  50. root: false,
  51. }
  52. }
  53. // SetMethodConfig is used to set config on specified method
  54. func (group *RouterGroup) SetMethodConfig(config *MethodConfig) *RouterGroup {
  55. group.baseConfig = config
  56. return group
  57. }
  58. // BasePath router group base path.
  59. func (group *RouterGroup) BasePath() string {
  60. return group.basePath
  61. }
  62. func (group *RouterGroup) handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes {
  63. absolutePath := group.calculateAbsolutePath(relativePath)
  64. injections := group.injections(relativePath)
  65. handlers = group.combineHandlers(injections, handlers)
  66. group.engine.addRoute(httpMethod, absolutePath, handlers...)
  67. if group.baseConfig != nil {
  68. group.engine.SetMethodConfig(absolutePath, group.baseConfig)
  69. }
  70. return group.returnObj()
  71. }
  72. // Handle registers a new request handle and middleware with the given path and method.
  73. // The last handler should be the real handler, the other ones should be middleware that can and should be shared among different routes.
  74. // See the example code in doc.
  75. //
  76. // For HEAD, GET, POST, PUT, and DELETE requests the respective shortcut
  77. // functions can be used.
  78. //
  79. // This function is intended for bulk loading and to allow the usage of less
  80. // frequently used, non-standardized or custom methods (e.g. for internal
  81. // communication with a proxy).
  82. func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes {
  83. if matches, err := regexp.MatchString("^[A-Z]+$", httpMethod); !matches || err != nil {
  84. panic("http method " + httpMethod + " is not valid")
  85. }
  86. return group.handle(httpMethod, relativePath, handlers...)
  87. }
  88. // HEAD is a shortcut for router.Handle("HEAD", path, handle).
  89. func (group *RouterGroup) HEAD(relativePath string, handlers ...HandlerFunc) IRoutes {
  90. return group.handle("HEAD", relativePath, handlers...)
  91. }
  92. // GET is a shortcut for router.Handle("GET", path, handle).
  93. func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
  94. return group.handle("GET", relativePath, handlers...)
  95. }
  96. // POST is a shortcut for router.Handle("POST", path, handle).
  97. func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes {
  98. return group.handle("POST", relativePath, handlers...)
  99. }
  100. // PUT is a shortcut for router.Handle("PUT", path, handle).
  101. func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes {
  102. return group.handle("PUT", relativePath, handlers...)
  103. }
  104. // DELETE is a shortcut for router.Handle("DELETE", path, handle).
  105. func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes {
  106. return group.handle("DELETE", relativePath, handlers...)
  107. }
  108. func (group *RouterGroup) combineHandlers(handlerGroups ...[]HandlerFunc) []HandlerFunc {
  109. finalSize := len(group.Handlers)
  110. for _, handlers := range handlerGroups {
  111. finalSize += len(handlers)
  112. }
  113. if finalSize >= int(_abortIndex) {
  114. panic("too many handlers")
  115. }
  116. mergedHandlers := make([]HandlerFunc, finalSize)
  117. copy(mergedHandlers, group.Handlers)
  118. position := len(group.Handlers)
  119. for _, handlers := range handlerGroups {
  120. copy(mergedHandlers[position:], handlers)
  121. position += len(handlers)
  122. }
  123. return mergedHandlers
  124. }
  125. func (group *RouterGroup) calculateAbsolutePath(relativePath string) string {
  126. return joinPaths(group.basePath, relativePath)
  127. }
  128. func (group *RouterGroup) returnObj() IRoutes {
  129. if group.root {
  130. return group.engine
  131. }
  132. return group
  133. }
  134. // injections is
  135. func (group *RouterGroup) injections(relativePath string) []HandlerFunc {
  136. absPath := group.calculateAbsolutePath(relativePath)
  137. for _, injection := range group.engine.injections {
  138. if !injection.pattern.MatchString(absPath) {
  139. continue
  140. }
  141. return injection.handlers
  142. }
  143. return nil
  144. }