group.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
  2. // 🤖 Github Repository: https://github.com/gofiber/fiber
  3. // 📌 API Documentation: https://docs.gofiber.io
  4. package fiber
  5. import (
  6. "fmt"
  7. "reflect"
  8. "strings"
  9. "sync/atomic"
  10. )
  11. // Group struct
  12. type Group struct {
  13. app *App
  14. name string
  15. Prefix string
  16. }
  17. // Mount attaches another app instance as a sub-router along a routing path.
  18. // It's very useful to split up a large API as many independent routers and
  19. // compose them as a single service using Mount.
  20. func (grp *Group) Mount(prefix string, fiber *App) Router {
  21. stack := fiber.Stack()
  22. groupPath := getGroupPath(grp.Prefix, prefix)
  23. groupPath = strings.TrimRight(groupPath, "/")
  24. if groupPath == "" {
  25. groupPath = "/"
  26. }
  27. for m := range stack {
  28. for r := range stack[m] {
  29. route := grp.app.copyRoute(stack[m][r])
  30. grp.app.addRoute(route.Method, grp.app.addPrefixToRoute(groupPath, route))
  31. }
  32. }
  33. // Support for configs of mounted-apps and sub-mounted-apps
  34. for mountedPrefixes, subApp := range fiber.appList {
  35. grp.app.appList[groupPath+mountedPrefixes] = subApp
  36. subApp.init()
  37. }
  38. atomic.AddUint32(&grp.app.handlersCount, fiber.handlersCount)
  39. return grp
  40. }
  41. // Name Assign name to specific route.
  42. func (grp *Group) Name(name string) Router {
  43. grp.app.mutex.Lock()
  44. if strings.HasPrefix(grp.Prefix, grp.app.latestGroup.Prefix) {
  45. grp.name = grp.app.latestGroup.name + name
  46. } else {
  47. grp.name = name
  48. }
  49. grp.app.latestGroup = grp
  50. if err := grp.app.hooks.executeOnGroupNameHooks(*grp.app.latestGroup); err != nil {
  51. panic(err)
  52. }
  53. grp.app.mutex.Unlock()
  54. return grp
  55. }
  56. // Use registers a middleware route that will match requests
  57. // with the provided prefix (which is optional and defaults to "/").
  58. //
  59. // app.Use(func(c *fiber.Ctx) error {
  60. // return c.Next()
  61. // })
  62. // app.Use("/api", func(c *fiber.Ctx) error {
  63. // return c.Next()
  64. // })
  65. // app.Use("/api", handler, func(c *fiber.Ctx) error {
  66. // return c.Next()
  67. // })
  68. //
  69. // This method will match all HTTP verbs: GET, POST, PUT, HEAD etc...
  70. func (grp *Group) Use(args ...interface{}) Router {
  71. prefix := ""
  72. var handlers []Handler
  73. for i := 0; i < len(args); i++ {
  74. switch arg := args[i].(type) {
  75. case string:
  76. prefix = arg
  77. case Handler:
  78. handlers = append(handlers, arg)
  79. default:
  80. panic(fmt.Sprintf("use: invalid handler %v\n", reflect.TypeOf(arg)))
  81. }
  82. }
  83. grp.app.register(methodUse, getGroupPath(grp.Prefix, prefix), handlers...)
  84. return grp
  85. }
  86. // Get registers a route for GET methods that requests a representation
  87. // of the specified resource. Requests using GET should only retrieve data.
  88. func (grp *Group) Get(path string, handlers ...Handler) Router {
  89. path = getGroupPath(grp.Prefix, path)
  90. return grp.app.Add(MethodHead, path, handlers...).Add(MethodGet, path, handlers...)
  91. }
  92. // Head registers a route for HEAD methods that asks for a response identical
  93. // to that of a GET request, but without the response body.
  94. func (grp *Group) Head(path string, handlers ...Handler) Router {
  95. return grp.Add(MethodHead, path, handlers...)
  96. }
  97. // Post registers a route for POST methods that is used to submit an entity to the
  98. // specified resource, often causing a change in state or side effects on the server.
  99. func (grp *Group) Post(path string, handlers ...Handler) Router {
  100. return grp.Add(MethodPost, path, handlers...)
  101. }
  102. // Put registers a route for PUT methods that replaces all current representations
  103. // of the target resource with the request payload.
  104. func (grp *Group) Put(path string, handlers ...Handler) Router {
  105. return grp.Add(MethodPut, path, handlers...)
  106. }
  107. // Delete registers a route for DELETE methods that deletes the specified resource.
  108. func (grp *Group) Delete(path string, handlers ...Handler) Router {
  109. return grp.Add(MethodDelete, path, handlers...)
  110. }
  111. // Connect registers a route for CONNECT methods that establishes a tunnel to the
  112. // server identified by the target resource.
  113. func (grp *Group) Connect(path string, handlers ...Handler) Router {
  114. return grp.Add(MethodConnect, path, handlers...)
  115. }
  116. // Options registers a route for OPTIONS methods that is used to describe the
  117. // communication options for the target resource.
  118. func (grp *Group) Options(path string, handlers ...Handler) Router {
  119. return grp.Add(MethodOptions, path, handlers...)
  120. }
  121. // Trace registers a route for TRACE methods that performs a message loop-back
  122. // test along the path to the target resource.
  123. func (grp *Group) Trace(path string, handlers ...Handler) Router {
  124. return grp.Add(MethodTrace, path, handlers...)
  125. }
  126. // Patch registers a route for PATCH methods that is used to apply partial
  127. // modifications to a resource.
  128. func (grp *Group) Patch(path string, handlers ...Handler) Router {
  129. return grp.Add(MethodPatch, path, handlers...)
  130. }
  131. // Add allows you to specify a HTTP method to register a route
  132. func (grp *Group) Add(method, path string, handlers ...Handler) Router {
  133. return grp.app.register(method, getGroupPath(grp.Prefix, path), handlers...)
  134. }
  135. // Static will create a file server serving static files
  136. func (grp *Group) Static(prefix, root string, config ...Static) Router {
  137. return grp.app.registerStatic(getGroupPath(grp.Prefix, prefix), root, config...)
  138. }
  139. // All will register the handler on all HTTP methods
  140. func (grp *Group) All(path string, handlers ...Handler) Router {
  141. for _, method := range intMethod {
  142. _ = grp.Add(method, path, handlers...)
  143. }
  144. return grp
  145. }
  146. // Group is used for Routes with common prefix to define a new sub-router with optional middleware.
  147. //
  148. // api := app.Group("/api")
  149. // api.Get("/users", handler)
  150. func (grp *Group) Group(prefix string, handlers ...Handler) Router {
  151. prefix = getGroupPath(grp.Prefix, prefix)
  152. if len(handlers) > 0 {
  153. _ = grp.app.register(methodUse, prefix, handlers...)
  154. }
  155. return grp.app.Group(prefix)
  156. }
  157. // Route is used to define routes with a common prefix inside the common function.
  158. // Uses Group method to define new sub-router.
  159. func (grp *Group) Route(prefix string, fn func(router Router), name ...string) Router {
  160. // Create new group
  161. group := grp.Group(prefix)
  162. if len(name) > 0 {
  163. group.Name(name[0])
  164. }
  165. // Define routes
  166. fn(group)
  167. return group
  168. }