Rest api with Golang and Postgresql using Beego Framework

Rest api with Golang and Postgresql using Beego Framework

·

12 min read

Go is one of the most used backend development languages actually, which has many advantages. This language currently has several frameworks, each with different learning curves and different advantages. In this article I will show you how to make an api rest using beego and that connects to a postgresql database.

Why Beego.

the beego framework is used for api rest, web applications and backend services in golang, it can be similar to Django which is a python framework, beego does not require third party installations, it handles Model-View-Controller (MVC) architecture, additionally it has a command line interface (CLI) called Bee Tool.

It integrates the Object Relationship Map (ORM) that helps to organize the application's database along with the session management tools and registration systems. It also incorporates a cache driver and libraries to operate HTTP elements. Another great feature is that it works well with command line tools.

Due to its extensive features and functionality it is not a tool that is usually used by beginners

Table of contents

  • Installation of beego and bee tool
  • Creation of api using bee tool
    • db model
    • create api
  • Additional adjustments to the api
  • Run Api
  • Use api
  • Enable Cors
  • Use of swagger

you can access the project repository

Installation

you need go version >= 1.14 .

# allow downloading of go modules
go env -w GO111MODULE=on
# installation of beego
go get github.com/beego/beego/v2
# bee tool installation
go get github.com/beego/bee/v2

no further steps are needed to install beego, you can verify the installation by running bee version on your computer, you should see something like the following:

______
| ___ \
| |_/ /  ___   ___
| ___ \ / _ \ / _ \
| |_/ /|  __/|  __/
\____/  \___| \___| v2.0.2

├── Beego     : Beego is not installed. Please do consider installing it first: https://github.com/beego/beego/v2. If you are using go mod, and you don't install the beego under $GOPATH/src/github.com/astaxie, just ignore this.
├── GoVersion : go1.15
├── GOOS      : linux
├── GOARCH    : amd64
├── NumCPU    : 8
├── GOPATH    : /go
├── GOROOT    : /usr/local/go
├── Compiler  : gc
└── Date      : Monday, 18 Jan 2021

you can ignore the line that says Beego is not installed

Creation of api using bee tool

For this example, a small hero data model will be provided

Data model

hero.png

get data model script

Creation api

To integrate with github and be able to use native go commands to get modules it is recommended to create the project in the following path

${GOPATH}/src/github.com/[user name or organization name]

in my case

${GOPATH}/src/github.com/BOTOOM

for the creation of the api use the following command

bee api heroes_crud -driver=postgres -conn="postgres://[database user]:[database password]@[database host or url]:[optionar database port]/[database name]?sslmode=disable"

in my case

bee api heroes_crud -driver=postgres -conn="postgres://postgres:docker@192.168.0.17:5432/heroes?sslmode=disable"

After executing the command you will see something similar

image.png

your project will have a structure similar to this

image.png

Additional adjustments to the api

the api was already created using bee tool, but it is possible that errors are generated when creating the api so follow these steps

  • Adjustment of routes in imports

    before heroes_crud add github.com/[user name or organization name]/

    before change in the main.go file

      import (
          _ "heroes_crud/routers"
    
          beego "github.com/beego/beego/v2/server/web"
          "github.com/beego/beego/v2/client/orm"
          _ "github.com/lib/pq"
      )
    

    after change main.go

      import (
          _ "github.com/BOTOOM/heroes_crud/routers"
    
          beego "github.com/beego/beego/v2/server/web"
          "github.com/beego/beego/v2/client/orm"
          _ "github.com/lib/pq"
      )
    

    verify that the file routers/router.go contains the correct import, usually it is generated correctly ,for example

      package routers
    
      import (
          "github.com/BOTOOM/heroes_crud/controllers"
    
          beego "github.com/beego/beego/v2/server/web"
      )
    

    finally check the same in the drivers publisher.go ,hero.go and `power.go

  • Setting go.mod

    since go currently works with modules we must make a similar adjustment to the previous one but in the go.mod file

      module heroes_crud
    

    make the following change

      module github.com/BOTOOM/heroes_crud
    
  • database connection setting

      beego version 2 has had several changes among those to obtain the variables from the configuration file `conf/app.conf` , to avoid database connection errors make the following change in the `main.go
    
      func main() {
          orm.RegisterDataBase("default", "postgres", beego.AppConfig.String("sqlconn"))
          if beego.BConfig.RunMode == "dev" {
              beego.BConfig.WebConfig.DirectoryIndex = true
              beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
          }
          beego.Run()
      }
    

    creation of the variable sqlconn

      func main() {
          sqlconn, _ := beego.AppConfig.String("sqlconn")
          orm.RegisterDataBase("default", "postgres", sqlconn)
          if beego.BConfig.RunMode == "dev" {
              beego.BConfig.WebConfig.DirectoryIndex = true
              beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
          }
          beego.Run()
      }
    
  • Auto-incremental id setting for the id to be auto-incremental when making post requests add in the struct of each model ;auto after pk should be something like this, for the model of publisher.go:

      type Publisher struct {
          Id       int       `orm:"column(id);pk;auto"`
          Name     string    `orm:"column(name)"`
          Active   bool      `orm:"column(active);null"`
          CreateIn time.Time `orm:"column(create_in);type(timestamp without time zone);null"`
      }
    

    do the same for the other models.

  • Addition of RelatedSel() method

    beego has a method called RelatedSel that takes a foring key and makes a join in order to bring the data and not have to make another nested query, this function has a capacity of 5 levels

    to make use of it in the respective models in the GetAll method as an example in the hero.go model the GetAllHero method

    before the change

      // GetAllHero retrieves all Hero matches certain condition. Returns empty list if
      // no records exist
      func GetAllHero(query map[string]string, fields []string, sortby []string, order []string,
          offset int64, limit int64) (ml []interface{}, err error) {
          o := orm.NewOrm()
          qs := o.QueryTable(new(Hero))
    

    after change

      // GetAllHero retrieves all Hero matches certain condition. Returns empty list if
      // no records exist
      func GetAllHero(query map[string]string, fields []string, sortby []string, order []string,
          offset int64, limit int64) (ml []interface{}, err error) {
          o := orm.NewOrm()
          qs := o.QueryTable(new(Hero)).RelatedSel()
    

Run Api

To run the api run the following command at the root of the project

bee run

or

go run main.go

open your browser in localhost:8080 , podrá ver lo siguiente:

image.png

Use Api

you can use postman to make use of the api, for example to join a new publisher use a POST request, the endpoint http://localhost:8080/v1/publisher and the following body

{
    "Name": "Dc Comics",
    "Active": true
}

using postman

image.png

result using postman, the same endpoint is used for the GET method

image.png

you can use in the same endpoint the PUT and DELETE methods

Enable CORS

To enable cors copy the following lines into the main function of the main.go file this will allow the api to be consumed from web applications or other backend services

beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
        AllowOrigins: []string{"*"},
        AllowMethods: []string{"PUT", "PATCH", "GET", "POST", "OPTIONS", "DELETE"},
        AllowHeaders: []string{"Origin", "x-requested-with",
            "content-type",
            "accept",
            "origin",
            "authorization",
            "x-csrftoken"},
        ExposeHeaders:    []string{"Content-Length"},
        AllowCredentials: true,
    }))

It should look something like this:

package main

import (
    _ "github.com/BOTOOM/heroes_crud/routers"
    "github.com/beego/beego/v2/client/orm"
    beego "github.com/beego/beego/v2/server/web"
    "github.com/beego/beego/v2/server/web/filter/cors"
    _ "github.com/lib/pq"
)

func main() {
    sqlconn, _ := beego.AppConfig.String("sqlconn")
    orm.RegisterDataBase("default", "postgres", sqlconn)
    if beego.BConfig.RunMode == "dev" {
        beego.BConfig.WebConfig.DirectoryIndex = true
        beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
    }
    beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
        AllowOrigins: []string{"*"},
        AllowMethods: []string{"PUT", "PATCH", "GET", "POST", "OPTIONS", "DELETE"},
        AllowHeaders: []string{"Origin", "x-requested-with",
            "content-type",
            "accept",
            "origin",
            "authorization",
            "x-csrftoken"},
        ExposeHeaders:    []string{"Content-Length"},
        AllowCredentials: true,
    }))
    beego.Run()
}

verify that the cors are imported from "github.com/beego/beego/v2/server/web/filter/cors"

Use Swagger

Swagger is an apis documentation tool which can also be used for apis testing. To enable and create swagger files in your project run the following command in your terminal

bee run -downdoc=true -gendoc=true

open your browser in localhost:8080/swagger/ and see the following

image.png

at the end you will find the data models

image.png

to use swagger you just need to display the method you want to use by clicking on the Try it Out button and then on Execute

image.png

The result will be displayed there

image.png

Use of filters with swagger

The GetAll method generated with the api allows to make filters and queries which we can test from swagger.

For this example I have entered 2 super heroes Batman and Ironman, when performing the get method gives me the following answer

image.png

There we can see the data of the heroes but additionally we can see what their editorial brings , that is possible thanks to the method RelatedSel() that we previously configured.

Next we will make use of the filters to obtain only the super heroes of Dc Comics.

image.png

and the result will be

image.png

You can see that also in the section of 'Curl' at the beginning provides the request if used in any application.

Additionally you can use the other parameters like limit, offset, request only some fields using fields and be able to sort your results

Conclusion

Beego is a golang framework with a large amount of features and high functionality that allows developers to build a robust REST API in a short time and which can be strengthened by using documentation.


additionally be able to access: