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:

  1. Create MaeIn - A lightweight structure devoid of protocol information
  2. Send to Maestro - The controller (maestro) in X-Go framework processes the request
  3. Receive MaeOut - The maestro returns a lightweight structure, also devoid of protocol information
  4. 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"
}