Routing
In a web application, X-Go uses two levels of routing:
App-Level Routing
The app-level router allows you to run different commands and use the app via a CLI. This is where you define available commands for your application.
Location: src/app/app.go
Web Router
The web router is used when running the app as a web application. It handles HTTP routing by calling the web routing system, which uses the Gin Framework. Web routers are split into section routers for better organization.
Location: src/app/routers/
Example: Section Router
Here’s an example of a section router handling AJAX routes. Note that the router itself, along with routes and middlewares, are all injectable services. Routes and routers can be configured via middlewares - see the Middlewares page for more information.
package routers
import (
"github.com/gin-gonic/gin"
// [...]
)
type AjxRouter struct {
AutocompleteAjxRoute *ajx_routes.AutocompleteAjxRoute
AutologinMiddleware *middlewares.AutologinMiddleware
BlockBotsMiddleware *middlewares.BlockBotsMiddleware
SearchAjxRoute *ajx_routes.SearchAjxRoute
}
func (this *AjxRouter) Act(ctx context.Context, r *gin.Engine) {
router := r.Group("/ajx")
router.Use(this.AutologinMiddleware.Act())
router.Use(this.BlockBotsMiddleware.Act())
this.configureRoutes(router)
}
func (this *AjxRouter) configureRoutes(router *gin.RouterGroup) {
router.POST("autocomplete", this.AutocompleteAjxRoute.Act)
router.POST("search", this.SearchAjxRoute.Act)
}
Web Routes and Protocol Handling
Web routes are responsible for managing outer protocols (HTTP, HTML, JSON, etc.). They follow this pattern:
- Create MaeIn - A lightweight structure devoid of protocol information
- Send to Maestro - The controller (maestro) in X-Go framework processes the request
- Receive MaeOut - The maestro returns a lightweight structure, also devoid of protocol information
- Render Response - The route selects a protocol to render the MaeOut (HTML, JSON, etc.) and handles protocol-specific operations like HTTP status codes or redirections
Example: App Route
package routes
import (
// [...]
)
type NewGardenAppRoute struct {
AppRoute *route.AppRoute
NewGardenAppBinder *binders.NewGardenAppBinder
NewGardenMae *mae.NewGardenMae
NewGardenView *html_views.NewGardenView
}
func (this *NewGardenAppRoute) Act(c *gin.Context) (maestro.MaeIn, maestro.MaeOut) {
in := &maes.NewGardenMaeIn{}
this.AppRoute.PopulateInContext(c, &in.Context)
this.NewGardenAppBinder.Bind(c, in, c)
out, errMae := this.NewGardenMae.Act(c, in)
if errMae != nil {
panic(errMae)
}
this.AppRoute.RenderView(c, func() goc.HTML {
return this.NewGardenView.H(out)
}, &out.Extra)
return in, out
}
func (this *NewGardenAppRoute) GetRoutePath() string {
return "new-garden"
}
func (this *NewGardenAppRoute) GetMethod() string {
return "GET"
}