programming

09 Configuring HTTP Router, HTTP Server and Database Connection

At this stage we will create the main function of the project that we have created. In the main function we will add several function initializations which are used to initialize all the resources needed by the project such as database connections, handler initialization, usecases and repositories that we have previously created.

The HTTP Router that we use in this project is

	github.com/julienschmidt/httprouter

So we need to first add the package to our project using the golang module command.

	go get github.com/julienschmidt/httprouter

Configuring HTTP Router and HTTP ServerA

First, we create a main.go file in the cmd folder then fill the file with the code below.

package cmd

import (
	"database/sql"

	"github.com/julienschmidt/httprouter"
	httpHandler "github.com/santekno/learn-golang-restful/delivery/http"
	mysqlRepository "github.com/santekno/learn-golang-restful/repository/mysql"
	articleUsecase "github.com/santekno/learn-golang-restful/usecase/article"
)

func main() {
	router := httprouter.New()

	repository := mysqlRepository.New(&sql.DB{})
	articleUsecase := articleUsecase.New(repository)
	articleHandler := httpHandler.New(articleUsecase)

	router.GET("/api/articles", articleHandler.GetAll)
	router.GET("/api/articles/:article_id", articleHandler.GetByID)
	router.POST("/api/articles/", articleHandler.Store)
	router.PUT("/api/articles/:article_id", articleHandler.Update)
	router.DELETE("/api/articles/:article_id", articleHandler.Delete)

  server := http.Server{
		Addr:    "localhost:3000",
		Handler: router,
	}

	err := server.ListenAndServe()
	if err != nil {
		panic(err)
	}
}

We can see that the first initialization done is

	router := httprouter.New()

This httprouter initialization is done every time there is a REST API initialization if we use the package from julienschmidt/httprouter.

Next we initialize the repository, usecase and handler layers that we have previously created.

	repository := mysqlRepository.New(&sql.DB{})
	articleUsecase := articleUsecase.New(repository)
	articleHandler := httpHandler.New(articleUsecase)

In initializing repository we need to add a database connection to the layer which will be explained in the database connection configuration section.

Followed by creating each endpoint that we previously defined using the API Specification. Make sure the method and entrypoint are the same as in the documentation.

	router.GET("/api/articles", articleHandler.GetAll)
	router.GET("/api/articles/:article_id", articleHandler.GetByID)
	router.POST("/api/articles/", articleHandler.Store)
	router.PUT("/api/articles/:article_id", articleHandler.Update)
	router.DELETE("/api/articles/:article_id", articleHandler.Delete)

And the last is the HTTP Server to make our REST API server public with a configuration like this.

  server := http.Server{
    Addr:    "localhost:3000",
    Handler: router,
  }

  err := server.ListenAndServe()
  if err != nil {
    panic(err)
  }

MySQL Database Connection Configuration

In this database connection we use an additional package to support connections to the MySQL database, namely

github.com/go-sql-driver/mysql 

Then we need to add the package/libary first with this command.

go get github.com/go-sql-driver/mysql 

Then we create the pkg/database folder and create the mysql.go file then fill the file with the code below.

package database

import (
	"database/sql"
	"os"

	"gorm.io/driver/mysql"
)

unc New() *sql.DB {
	cfg := mysql.Config{
		User: os.Getenv("DATABASE_USER"),
		Passwd: os.Getenv("DATABASE_PASS"),
		Net:                  "tcp",
		Addr: os.Getenv("DATABASE_ADDRESS"),
		DBName: os.Getenv("DATABASE_NAME"),
		AllowNativePasswords: true,
		ParseTime: true,
	}

	var err error
	db, err := sql.Open("mysql", cfg.FormatDSN())
	if err != nil {
		log.Fatal(err)
	}

	pingErr := db.Ping()
	if pingErr != nil {
		log.Fatal(pingErr)
	}

	fmt.Println("Connected!")
	return db
}

In this project we only do basic configuration including

ConfigurationInformation
Useruser connection required to mysql database
Passwdthe passowrd for the user required for connection to the mysql database
Netthe protocol used to connect to the database
Addrthe address indicating the server of the database
DBNamethe name of the destination database

Next add the database connection to the main.go file and change the main() function as below.

func main() {
	// initialize http router
	router := httprouter.New()

	// initialize database
	db := database.New()

	// initialize repository
	repository := mysqlRepository.New(db)
	// initialize usecase
	articleUsecase := articleUsecase.New(repository)
	// handler initialization
	articleHandler := httpHandler.New(articleUsecase)

	// entrypoint
	router.GET("/api/articles", articleHandler.GetAll)
	router.GET("/api/articles/:article_id", articleHandler.GetByID)
	router.POST("/api/articles/", articleHandler.Store)
	router.PUT("/api/articles/:article_id", articleHandler.Update)
	router.DELETE("/api/articles/:article_id", articleHandler.Delete)
}

Create .env file

We will make all the configuration stored in one .env file so that when we want to change all the configuration it is easier and easier to just replace it in the file. So we will try to create a .env file and fill the file with this.

DATABASE_USER=development
DATABASE_PASS=d3v3l0pm3nt
DATABASE_ADDRESS=localhost:3306
DATABASE_NAME=article

then add this library package to read the .env file

go get github.com/joho/godotenv

and add the code below to the main.go file at the top of the main() function.

	err := godotenv.Load(".env")
	if err != nil {
		log.Fatalf("error loading .env file")
	}
comments powered by Disqus