Golang MW

Version


The below documentation are for Version 1.0.0. If you are using an older version check out the documentation for version 0.1.0

Objective


The Golang Middleware provides the ability to modernize existing API with SOAJS when this API is built using Golang as a development language.

The middleware exposes several functionality and configuration that SOAJS offers and which can be consumed by the API upon initialization or during runtime when requests arrive.

This page explains the Golang middleware; the functionality and configuration that it offers, how to install it and how to use it.

Scenario


  1. How to Install 
  2. Using the Middleware
    1. Initialization State
    2. Runtime State
  3. Features
    1. Configuration
    2. Functionality
  4. How does it work
    1. on init
    2. on request
  5. Examples
    1. Golang gorilla/mux


1- How to Install


The SOAJS Golang middleware is open source and is available under Github, you can use the following reference to pull the source code → https://github.com/soajs/soajs.golang

The middleware is also available to download using the go get command.

SOAJS golang
# install from github
go get github.com/soajs/soajs.golang


2- Using the Middleware


You need to add soa.json file to your repository

soa.json
{
    "type": "service",

    "serviceName": "golangservice",
    "serviceGroup": "Custom Services",
    "servicePort": 4383,
    "serviceVersion": "1",

    "requestTimeout": 30,
    "requestTimeoutRenewal": 5,
    "extKeyRequired": true,
    "urac": true,
    "urac_Profile": true,
    "oauth": true,
    "urac_ACL": false,
    "provision_ACL": false,
    "swagger": true,

    "prerequisites": {
        "cpu": " ",
        "memory": " "
    },

    "maintenance": {
        "port": {
            "type": "inherit"
        },
        "readiness": "/heartbeat"
    }
}

Once you download the middleware, simply require it and instruct the web application server to use it. Consequently, anywhere in your APIs, invoke soajs context in the request to access the data and functions that it offers.

Using the Middleware with Golang
package main

import (
	"github.com/soajs/soajs.golang"
)

func Foo(w http.ResponseWriter, r *http.Request) {
	// ...

	//Get SOAJS Header Object
	soajs := r.Context().Value(soajsgo.SoajsKey).(soajsgo.ContextData)
	log.Println(soajs)

	// ...
}

func main() {
    router := mux.NewRouter()

	//Load soa.json
	jsonFile, err := os.Open("soa.json")
	if err != nil {
		panic(err)
	}
	defer jsonFile.Close()
	byteValue, _ := ioutil.ReadAll(jsonFile)
	var result soajsgo.Config
	json.Unmarshal([]byte(byteValue), &result)

	//Turn on SOAJS middleware
	soajs, err := soajsgo.NewFromConfig(context.Background(),result)
	if err != nil{
		log.Fatal(err)
	}
	router.Use(soajs.Middleware)


    router.HandleFunc("/foo", Foo).Methods("POST")

	// ...


	port := fmt.Sprintf(":%d", result.ServicePort)
	log.Fatal(http.ListenAndServe(port, router))
}


3- Features


Once the middleware is initialized, the following functionality becomes available helping pull resources configuration from the registry:

FunctionTypeInputOutputRemarks
DatabaseMethoddbName

returns database object

Mongo Client Driver
DatabasesMethod-returns all core and tenant meta databasesMongo Client Driver
ResourceMethodresourceNamereturns resource objectRegistry
ServiceMethodserviceName

returns service object

Service
ReloadMethod-returns boolean true or false, depending on the success of the reload operationRegistry
CustomField-Access to custom registryRegistry

This middleware functionality is accessible via the request that is made to the API. The middleware traps the request once it hits the API, injects its functionality and then hands it back to you to add your business logic. 

Access the registry On Init

Get Registry on Init
func main() {
	// ...

	soajs, err := soajsgo.NewFromConfig(context.Background(),result)
	router.Use(soajs.Middleware)

	mongoCluster, error := soajs.Resource("myMongo")

	// ...
}

Access the registry On Request

Get Registry on Request
func Foo(w http.ResponseWriter, r *http.Request) {
	// ...

	//Get SOAJS Header Object
	soajs := r.Context().Value(soajsgo.SoajsKey).(soajsgo.ContextData)
	
	mongoCluster, error := soajs.Reg.Resource("myMongo")

	// ...
}


4- How does it work


On Init

The Middleware requires the following environment variables to be set prior to starting your service

Environment VariableDescriptionExampleReference

SOAJS_REGISTRY_API

The location of the SOAJS API Gateway along with the maintenance port value that it is using in the environment where the service will run in127.0.0.1:5000/Environment Variables

SOAJS_ENV

environment code that this service will run inDEVEnvironment Variables

Once your service starts, the middleware will make a call to the API Gateway and retrieve the registry of the environment, it will cache it in memory.

From this registry, it uses variable autoReloadRegistry (which represents the auto reload duration in seconds) and every time this value is met, the middleware automatically pulls the new version of the registry and updates its cached version.

On request

SOAJS middleware augments your service by trapping all arriving requests and injecting additional data then hands the updated version of request to your business logic.

The following table illustrates the data that gets injected by the middleware on every request:

Once you fetch the soajs Object from the header context as follow:

Get Registry on Init
func Foo(w http.ResponseWriter, r *http.Request) {
	// ...

	//Get SOAJS Header Object
	soajs := r.Context().Value(soajsgo.SoajsKey).(soajsgo.ContextData)
	
	mongoCluster, error := soajs.Reg.Resource("myMongo")

	// ...
}


The following will be available on the soajs object

PropertyCode SnippetDescriptionReference
Tenant
soajs.Tenant
{
    ID : '5c17cda54adb9ddba2a29a1d',
    Code : 'DEMO',
	Key : { 
		IKey : '',
		EKey: ''
	},
	Application : { 
    	product : '',
    	package : '',
    	appId : '',
    	acl : {},
    	acl_all_env : {}
	},
   Main : {
    ID : '1213232',
    Code : 'wwww'
  }
}

id & code: Represents the tenant information that is making the call to the API.

Application: Represents the product that is making the call to the API.

Key: Represents the key that is making the call to the API.

Main: is the tenant info about the main tenant 

Multitenancy

Device

soajs.Device
'Mozilla/5.0 (Macintosh; ..'
Represents the device used while making the call to the API.

Security

Services Config

Geo
soajs.Geo
{
	"ip": "..."
}
Represents the IP used while making the call to the API.
ServicesConfig
soajs.ServicesConfig
{
	"key" : "value .."
}
Multi tenant configuration for this API for this tenant key 
Urac
soajs.Urac
{
		"_id": "",
		"username": "",
		"firstName": "",
		"lastName": "",
		"email": "",
		"groups": "",
		"tenant": {
			"id": "",
			"code": ""
		},
		"profile": {
			//extra information
		},
		"acl": "",
		"acl_AllEnv": ""
}
Represents the User record that is accessing the API.URAC v2
Awareness
soajs.Awareness
{
    Host : '',
    Port : '',
    Path : 'function'
}

Represents the SOAJS API Gateway internal network host & port based on the environment where the API is deployed and running in.

This is useful to call other microservices as follow:

calling shoppingcart version 1
uri := soajs.Awareness.Path("shoppingcart", "1")
Request
Reg
soajs.Reg
mongoCluster, error := soajs.Reg.Resource("myMongo")

Registry object check point number 3 above



5- Examples


Golang gorilla/mux

The following code snippets shows a basic example built using gorilla/mux library and how the SOAJS Golang Middleware was added to the code to augment the web server created.

Full Example on: https://github.com/soajs/soajs.golang.mux