# Beego Code structure [Api Based App] ## Prerequisite - [Beego File Structure](https://hackmd.io/@haquenafeem/ryFlkeTuF) --- Lets Discuss with an example project : [beegotodo](https://github.com/nafeem-evatix/beegotodo) ## main.go File ```go= package main import ( _ "github.com/nafeem-evatix/beegotodo/routers" beego "github.com/beego/beego/v2/server/web" ) func main() { if beego.BConfig.RunMode == "dev" { beego.BConfig.WebConfig.DirectoryIndex = true beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" } beego.Run() } ``` - RunMode is `dev` - in this mode we can access /swagger where API documentations are served - when running `swagger` folder is created (how ? provided in file structure) - in the conditional block we are serving swagger folder as a static directory in the `/swagger` url - beego.Run() - it runs the application - whenever the program is ran, it reads configuration from `conf/app.conf` - which port to run the application - whether it is DDev or Prod mode - _ "github.com/nafeem-evatix/beegotodo/routers" - this calls `init()` from the routers package ## controllers/todo.go File [File](https://github.com/nafeem-evatix/beegotodo/blob/master/controllers/todo.go) ```go= type TodoController struct { beego.Controller } ``` - TodoController inherits from beego.Controller - beego.Controller is an implementation of `ControllerInterface` - it has methods like Post,Get,Delete,Put.... ```go= // URLMapping ... func (c *TodoController) URLMapping() { c.Mapping("Post", c.Post) c.Mapping("GetOne", c.GetOne) c.Mapping("GetAll", c.GetAll) c.Mapping("Put", c.Put) c.Mapping("Delete", c.Delete) } ``` - this portion defines for which call which method is responsible - when we run the app, theres and auto generated file `commetsRouter_controllers` in `routers` package - here all the methods ar defined in GlobalControllerRouter map - there are other fields - but for now, Each of the Method is mapped using this `URLMapping()` ```go= // Post ... // @Title Post // @Description create Todo // @Param body body models.Todo true "body for Todo content" // @Success 201 {int} models.Todo // @Failure 403 body is empty // @router / [post] func (c *TodoController) Post() { var v models.Todo json.Unmarshal(c.Ctx.Input.RequestBody, &v) if _, err := models.AddTodo(&v); err == nil { c.Ctx.Output.SetStatus(201) c.Data["json"] = v } else { c.Data["json"] = err.Error() } c.ServeJSON() } ``` - lets take this block as an example - this basically is a handler method - whenever theres a request in .../todo/ and the method is `Post` this block of code is responsible for what to do with request - notice the comments before the method ? - these comments help generate API documentation - define routes - remember `commentsRouter_controllers` in `routers` package ? - `commentsRouter_controllers` this file is also generated from the comments - and it holds information which route is which method and gets mapped in the `URLMapping()` - similiarly there are other methods like GetOne,GetAll.... ## models/todo.go File [File](https://github.com/nafeem-evatix/beegotodo/blob/master/models/todo.go) - models are defined here - models are registered as orm through tagging - has methods whic are called by controller methods - database logics should go here ## routers/router.go [beego-doc-on-routing](https://beego.vip/docs/mvc/controller/router.md) ```go= // @APIVersion 1.0.0 // @Title beego Test API // @Description beego has a very cool tools to autogenerate documents for your API // @Contact astaxie@gmail.com // @TermsOfServiceUrl http://beego.me/ // @License Apache 2.0 // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html package routers import ( "github.com/nafeem-evatix/beegotodo/controllers" beego "github.com/beego/beego/v2/server/web" ) func init() { ns := beego.NewNamespace("/v1", beego.NSNamespace("/todo", beego.NSInclude( &controllers.TodoController{}, ), ), ) beego.AddNamespace(ns) } ``` - comments above are for Documentation - here namespaces are created - beego.NewNamespace("/v1") - we could create others like v2,v3 so on for different api versions - NewNamespace takes `...beego.LinkNamespace` - beego.NSNamespace("/todo") - defines route /todo - and beego.NSInclude defines which controller is responsible to handle this route in our case its `TodoController` - this block of code basically defines layers of url routing and their responsible handlers - has `prefix` - has `handler` -> `*ControllerRegister` - beego.AddNamespace(ns) - adds the defined namespace ## routers/commentsRouter_controllers.go ```go= package routers import ( beego "github.com/beego/beego/v2/server/web" "github.com/beego/beego/v2/server/web/context/param" ) func init() { beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"] = append(beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"], beego.ControllerComments{ Method: "Post", Router: "/", AllowHTTPMethods: []string{"post"}, MethodParams: param.Make(), Filters: nil, Params: nil}) beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"] = append(beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"], beego.ControllerComments{ Method: "GetAll", Router: "/", AllowHTTPMethods: []string{"get"}, MethodParams: param.Make(), Filters: nil, Params: nil}) beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"] = append(beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"], beego.ControllerComments{ Method: "GetOne", Router: "/:id", AllowHTTPMethods: []string{"get"}, MethodParams: param.Make(), Filters: nil, Params: nil}) beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"] = append(beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"], beego.ControllerComments{ Method: "Put", Router: "/:id", AllowHTTPMethods: []string{"put"}, MethodParams: param.Make(), Filters: nil, Params: nil}) beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"] = append(beego.GlobalControllerRouter["github.com/nafeem-evatix/beegotodo/controllers:TodoController"], beego.ControllerComments{ Method: "Delete", Router: "/:id", AllowHTTPMethods: []string{"delete"}, MethodParams: param.Make(), Filters: nil, Params: nil}) } ``` - this file pushes to `GlobalControllerRouter` - uses `filepath:controllername` as key - assigns `[]ControllerComments` to that key - notice each ControllerComments has - Methods, Router, AllowedHTTPMethods, MethodParams, Filters,Params - These are generated from the comments from controller ## Others -