# 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
-