// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️// 🤖 Github Repository: https://github.com/gofiber/fiber// 📌 API Documentation: https://docs.gofiber.iopackage fiberimport ()// Put fields related to mounting.type mountFields struct {// Mounted and main apps appList map[string]*App// Ordered keys of apps (sorted by key length for Render) appListKeys []string// check added routes of sub-apps subAppsRoutesAdded sync.Once// check mounted sub-apps subAppsProcessed sync.Once// Prefix of app if it was mounted mountPath string}// Create empty mountFields instancefunc newMountFields( *App) *mountFields {return &mountFields{appList: map[string]*App{"": },appListKeys: make([]string, 0), }}// Mount attaches another app instance as a sub-router along a routing path.// It's very useful to split up a large API as many independent routers and// compose them as a single service using Mount. The fiber's error handler and// any of the fiber's sub apps are added to the application's error handlers// to be invoked on errors that happen within the prefix route.func ( *App) ( string, *App) Router { = strings.TrimRight(, "/")if == "" { = "/" }// Support for configs of mounted-apps and sub-mounted-appsfor , := range .mountFields.appList { := getGroupPath(, ) .mountFields.mountPath = .mountFields.appList[] = }// register mounted group := &Group{Prefix: , app: } .register(methodUse, , )// Execute onMount hooksif := .hooks.executeOnMountHooks(); != nil {panic() }return}// Mount attaches another app instance as a sub-router along a routing path.// It's very useful to split up a large API as many independent routers and// compose them as a single service using Mount.func ( *Group) ( string, *App) Router { := getGroupPath(.Prefix, ) = strings.TrimRight(, "/")if == "" { = "/" }// Support for configs of mounted-apps and sub-mounted-appsfor , := range .mountFields.appList { := getGroupPath(, ) .mountFields.mountPath = .app.mountFields.appList[] = }// register mounted group := &Group{Prefix: , app: } .app.register(methodUse, , )// Execute onMount hooksif := .hooks.executeOnMountHooks(.app); != nil {panic() }return}// The MountPath property contains one or more path patterns on which a sub-app was mounted.func ( *App) () string {return .mountFields.mountPath}// hasMountedApps Checks if there are any mounted apps in the current application.func ( *App) () bool {returnlen(.mountFields.appList) > 1}// mountStartupProcess Handles the startup process of mounted apps by appending sub-app routes, generating app list keys, and processing sub-app routes.func ( *App) () {if .hasMountedApps() {// add routes of sub-apps .mountFields.subAppsProcessed.Do(func() { .appendSubAppLists(.mountFields.appList) .generateAppListKeys() })// adds the routes of the sub-apps to the current application. .mountFields.subAppsRoutesAdded.Do(func() { .processSubAppsRoutes() }) }}// generateAppListKeys generates app list keys for Render, should work after appendSubAppListsfunc ( *App) () {for := range .mountFields.appList { .mountFields.appListKeys = append(.mountFields.appListKeys, ) }sort.Slice(.mountFields.appListKeys, func(, int) bool {returnlen(.mountFields.appListKeys[]) < len(.mountFields.appListKeys[]) })}// appendSubAppLists supports nested for sub appsfunc ( *App) ( map[string]*App, ...string) {// Optimize: Cache parent prefix := ""iflen() > 0 { = [0] }for , := range {// skip real appif == "" {continue }if != "" { = getGroupPath(, ) }if , := .mountFields.appList[]; ! { .mountFields.appList[] = }// The first element of appList is always the app itself. If there are no other sub apps, we should skip appending nested apps.iflen(.mountFields.appList) > 1 { .(.mountFields.appList, ) } }}// processSubAppsRoutes adds routes of sub-apps recursively when the server is startedfunc ( *App) () {for , := range .mountFields.appList {// skip real appif == "" {continue }// process the inner routesif .hasMountedApps() { .mountFields.subAppsRoutesAdded.Do(func() { .() }) } }varuint32varuint32// Iterate over the stack of the parent appfor := range .stack {// Iterate over each route in the stack := len(.stack[])for := 0; < ; ++ { := .stack[][]// Check if the route has a mounted appif !.mount { ++// If not, update the route's position and continue .pos = if !.use || (.use && == 0) { += uint32(len(.Handlers)) }continue }// Create a slice to hold the sub-app's routes := make([]*Route, len(.group.app.stack[]))// Iterate over the sub-app's routesfor , := range .group.app.stack[] {// Clone the sub-app's route := .copyRoute()// Add the parent route's path as a prefix to the sub-app's route .addPrefixToRoute(.path, )// Add the cloned sub-app's route to the slice of sub-app routes [] = }// Insert the sub-app's routes into the parent app's stack := make([]*Route, len(.stack[])+len()-1)copy([:], .stack[][:])copy([:+len()], )copy([+len():], .stack[][+1:]) .stack[] = // Decrease the parent app's route count to account for the mounted app's original routeatomic.AddUint32(&.routesCount, ^uint32(0)) --// Increase the parent app's route count to account for the sub-app's routesatomic.AddUint32(&.routesCount, uint32(len()))// Mark the parent app's routes as refreshed .routesRefreshed = true// update stackLen after appending subRoutes to app.stack[m] = len(.stack[]) } }atomic.StoreUint32(&.handlersCount, )}
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.