days
0
-38
-7
hours
0
-6
minutes
0
-9
seconds
-5
-1
search
A Golang MVC framework for building web services

Web Service with Go and Go-Web

Roberto Ferro
#go
go-web
© Shutterstock / Soraluk Chonvanich

Go-Web reduces the need for “repetitive” tasks like explicitly binding routes, actions, and middleware; while not problematic per se, programmers may want to adopt “ready-to-use” solutions, for instances if they want easily build complex services, aiming at a reduced “productive lag”.

Why Go-Web?

Go-Web adopts a “convention over configuration” approach similar to frameworks like Laravel [1], Symfony [2] and Rails [3].

By following this principle, Go-Web reduces the need for “repetitive” tasks like explicitly binding routes, actions, and middleware; while not problematic per se, programmers may want to adopt “ready-to-use” solutions, for instances if they want easily build complex services, aiming at a reduced “productive lag”.

Programmers may want to use existing frameworks like Gin-Gonic [4] and Go Buffalo [5], but Go-Web differs from them because of the aforementioned “convention over configuration” approach.

SEE ALSO: How Curve is getting ahead with Golang

Installation

You can install Go-Web as follows :

go-web

If you’re using Visual Studio Code you can install Go-Web framework with its specific extension: https://marketplace.visualstudio.com/items?itemName=Roberto.go-web

Architecture

Go-Web uses the so-called kernel in conjunction with the Service Container, file routes.yml and dependency gorilla/mux[9] to build the map that routes each incoming HTTP request to the appropriate method of a specific controller: after the initialization process, requests will be processed by the Go-Web black box. Figure 1 illustrates this process.

go-web

The startup process is executed once and uses reflection so that the service container can inject relevant bits of code into controllers; this approach allows controllers to access any service defined in the service container, like databases or log systems, reducing redundant (“boilerplate”) code.

While resolving a route is done by gorilla/mux, the execution of the code associated with the same route is performed (or tunneled) by the Service Container, which injects dependencies into the end-point controller: before going through a controller, a request may be processed by one or more middleware.

This workflow can be easily understood by looking at figure 2.

go-web

After being received by the Go-Web “black box”, a request may follow workflow starting in entry points A or B, figure 2.

Service container

The service container (fig. 3) is the tool that manages class dependencies and performs dependency injection through DIG.

By default, Go-Web implements some services, specifically, it leverages some libraries like gorilla/mux ([9]), gorm ([11]) and more.

go-web

As depicted in figure 3, the service container will register other services if correctly linked in the kernel: the process requires the implementation of such new services and further “registration” by adding them to Services array defined in Go-Web kernel

〈go-web〉/app/kernel/kernel.go

Development environment setup

Go-Web provides a docker-compose.yml file that allows developers to easily set up a new development environment: this requires both Docker [7] and Docker-compose [8] installed on the development system.

The docker-compose.yml defines several services, i.e. it is configured for providing instances of MySQL, Redis, MongoDB, and ElasticSearch; if needed, instances of other services may be added by modifying the docker-compose.yml file.

Service container

Configuring a service is straightforward and developers can use config.yml.example as an example for further customization; Go-Web will look for file config.yml, thus the aforementioned config.yml.example can be copied with such name.

The following listing demonstrates how a developer can configure both MySQL database and HTTP server.

go-web

The command-line interface

Go-Web has a built-in command-line interface that makes it easy for developers to use the framework. Before using the CLI, the developer needs to compile the project by running the command: go build goweb.go

After compiling the project, the CLI can be used to view all commands supported by Go-Web (see 1): ./goweb show:commands

The following listing table shows commands presented to the user by show:command:

go-web

Creating a controller

Being an MVC framework, Go-Web encourages the use of controllers, i.e. containers of the business logic of the application.

For instance, the controller named “SampleController” can be created by running the command:

./goweb controller:create sample

Go-Web will create the .go file containing controller named “SampleController” in the folder:

<go-web>/app/http/controller

The content of the newly created file will be:

go-web

When creating a controller, Go-Web will add to it the function Main, which could be expanded with some logic, as shown in listing 4; controllers can be extended by adding new public functions.

go-web

To gain access to everything underlying a Go-Web controller, including HTTP request and response, a controller needs to extend gwf.BaseController.

Because the service container is used to “resolve” all controllers in Go-Web, developers can type-hint any of their dependency because they will be injected into the controller instance, as represented by listing 5:

go-web

Note: both listings 4 and 5 include a call to gwf.ProcessError(err); this is how Go-Web can handle errors, but developers may adopt another approach.

SEE ALSO: Golang grows in the enterprise: Half of users program with Go daily

Registering controller

Updating routes is simple and requires little changes to routing.yml file, which is located in the root folder of the project. The definition of a route is, in fact, straightforward and routes can be organized in groups.

A route is defined by:

  • Path
    • Describers the URI of the route
    • a path is expressed as a string which could define parameters and supports regular expressions as gorilla/mux does ([9])
    • requests targeting undefined routes will cause a “client error” response with HTTP status 404 (not found)
    • example: ‘‘/hello-world’’
  • Action
    • describes the destination of a route as a combination of a controller and one of its functions
    • an action is expressed as the string 〈controller name〉@〈function name〉
    • if the action cannot be resolved (undefined controller or action), Go-Web will produce an error
    • example: SampleController@Main
  • Method
    • describes the HTTP verb supported by the route
    • a method must be one of the verbs supported by HTTP, i.e.:
      • GET
      • HEAD
      • POST
      • PUT
      • DELETE
      • CONNECT
      • OPTIONS
      • TRACE
      • PATCH
      • requests targeting an existing route with a wrong method (i.e. one that is not supported by the route) will cause a “client error” response with HTTP status 405 (method not allowed)
  • Middleware
    • represents the ordered list of middlewares that will process the request received by the route before performing the route’s action
    • the value of this property is a yml list of strings which must identify existing middleware
    • Example: Logging
  • ● Description (optional)
    • a string describing the purpose of the route
    • example: Returns JSON {‘‘message’’: ‘‘Hello World’’}

Running HTTP server

After creating a controller, registering it in the kernel and creating the binding with a route, the developer can run the server to ensure that the solution works; running a server can be done by running Go-Web like

./goweb server:run

The server will start listening on the port defined in file config.yml.

Creating middleware

Like controllers (section 7), middleware can be created with the command

./goweb middleware:create <middleware name>

For instance, middleware named “Passthrough” can be created by running the command

./goweb middleware:create passthrough

After executing the command, the newly created middleware will be available in the folder

〈go-web〉/app/http/middleware

As described in subsection 7.2, middlewares can be used for pre-processing requests received by routes defined in file routing.yml.

Creating async jobs

Go-web allows developers to create and schedule asynchronous jobs that will be dispatched in a queue. Like controllers, models and other entities, a job can be created with the CLI by running the command

./goweb job:create <job name>

Go-Web uses Redis to manage queues and developers can handle jobs with functions Schedule and Execute. The following listing illustrates an example of a Go-Web job:

go-web

Once scheduled, a job can be run with CLI command

./goweb queue:run <queue name>

The default queue can be run with the command

./goweb queue:run default

Creating CLI commands

Go-Web command-line interface (CLI) can be extended by running the command

./goweb cmd:create <name>

Before being available to Go-Web, commands must be registered in the console kernel at

〈go-web〉/app/console/kernel.go

The following listing shows the registration of command Greetings:

go-web

The command registration Commands variable is used by Go-Web to recognize and list supported commands.

Database handling

Create a new model

In MVC frameworks models are responsible for the database interaction logic. Go-Web takes advantage of GORM library to provide them. To create a new model you can use its specific CLI command:

./goweb model:create <model name>

Models are located in <go-web>/database/model directory.

Migrations

Migrations are like version control for your database, allowing your team to easily modify and share the application’s database schema. Developers can create new migration as follows:

./goweb migration:create <migration_name>

Developers can find its newly created migration files in <go-web>/database/migration directory.

SEE ALSO: GitHub releases Golang library for Elasticsearch – Meet Vulcanizer a focused Go API

Seeding

By implementing the “Seed” method you’ve been able to seed your table with “fake” data. Go-Web uses https://github.com/brianvoe/gofakeit as a faker library.

go-web

Authentication

By default, Go-Web provides two ways for authenticating users:

  • JWT-based authentication
  • basic (base) authentication

JWT-based authentication

Commonly used to authenticate users thought mobile applications or a SPA, JWT [15] authentication is implemented by function JWTAuthentication of controller AuthController or, in Go-Web terms, by the endpoint

AuthController@JWTAuthentication

The JSON structure used to represent credentials of a user must conform to JSON

go-web

The result of a successful login attempt with this type of authentication is an HTTP response containing a JWT token.

Resource access can be restricted only to authenticated users by adding middleware Auth to specific routes.

Basic (base) authentication

Basic, or base, authentication is the simplest way to authenticate users for service access; this method is implemented by the endpoint

AuthController@BasicAuth

The base authentication requires the same data structure as the JWT-based method (see listing 9) and routes can be protected by using middleware BasicAuth.

More than APIs: React and Redux scaffolding

Introduction

While Go-Web does not dictate which technology developers should use when building applications consuming APIs made with this Go-Web framework, it does provide foundations for building apps by suggesting the use of React and Redux.

Front-end assets and files can be found in the folder

〈go-web〉/assets

Specifically, the structure of the assets folder is simple and contains the following subfolders:

  • Js
    • contains JavaScript files used by the front-end application;
  • Css
    • contains JavaScript files used by the front-end application;
  • View
    • contains HTML views

Because Go-Web suggests using React and Redux, developers who want to use this stack must install appropriate tools on the development machine, like NodeJS and NPM; this document will not cover React, Redux or other front-end related topics other than few “basic” concepts.

For instance, the core single page application can be installed by running the command

npm install

Using views

Views are implemented by package http/template; Go-Web provides a simple helper to return a view from a controller, as reported in the following example:

go-web

Helper function View accepts three parameters:

  • the view’s path
  • the HTTP response returned by the controller
  • the interface used to “fill” the view

About the future

Go-Web is currently under active development and aims to become valid, Go alternative to well-known frameworks like Rails and Laravel.

References

[1] Laravel is a free, open-source PHP web framework, created by Taylor Otwell and intended for the development of web applications following the model–view–controller (MVC) architectural pattern and based on Symfony. Some of the features of Laravel are a modular packaging system with a dedicated dependency manager, different ways for accessing relational databases, utilities that aid in application deployment and maintenance, and its orientation toward syntactic sugar.

https://laravel.com/

[2] Symfony is a PHP web application framework and a set of reusable PHP components/libraries. It was published as free software on October 18, 2005 and released under the MIT license.

https://symfony.com/

[3] Ruby on Rails, or Rails, is an MVC server-side web application framework written in Ruby.

https://rubyonrails.org/

[4] One of the major Golang web frameworks

https://gin-gonic.com/

[5] Another Golang web framework

https://gobuffalo.io/en/

[6] Simple comparison between Golang and other major languages.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/go.html

[7] Docker is a set of platform as a service (PaaS) products that use OS-level virtualization to deliver software in packages called containers. Containers are isolated from one another and bundle their own software, libraries and configuration files; they can communicate with each other through well-defined channels. All containers are run by a single operating-system kernel and are thus more lightweight than virtual machines.

https://www.docker.com/

[8] Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services.

https://docs.docker.com/compose/

[9] Package mux implements a request router and dispatcher. The name mux stands for ”HTTP request multiplexer”. Like the standard http.ServeMux, mux.Router matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions.

https://www.gorillatoolkit.org/pkg/mux

[10] A reflection based dependency injection toolkit for Go.

https://github.com/uber-go/dig

[11] An ORM library for Go lang.

https://gorm.io/

[12] An elegant wrapper around Webpack.

https://laravel-mix.com/

[13] Node.js is an open-source, cross-platform, JavaScript runtime environment that executes JavaScript code outside of a browser.

https://nodejs.org/

[14] Npm (originally short for Node Package Manager) is a package manager for the JavaScript programming language.

https://www.npmjs.com/

[15] JSON Web Tokens are an open, industry-standard RFC 7519 method for representing claims securely between two parties.

https://jwt.io/

Author
go-web

Roberto Ferro

Roberto is a Software Engineer with 10 years of experience. Throughout his career, he developed software of increasing complexity with diverse technologies and covered several roles, including Solution Architect and Project Manager.


guest
0 Comments
Inline Feedbacks
View all comments