VCF Automation Blog

from Stefan Schnell

In the area of software testing and experimenting the use of a mock-up web server can be regarded as a normal standard. So I asked myself if these procedure could be used within Aria Automation without having to use additional tools or libraries. This blog post describes how exactly this can be achieved in Aria Automation.

How to Mock a Web Server


Node.js - Mock Web Server

A web server can be easily created with the Node.js runtime environment, which is also available in Aria Automation. An easy example of a web server is available at the Node.js documentation. We use the same approach here, but with a few additions and changes: Hello World is returned with every request. The web server is simply created as an action of the Node.js runtime environment.

/**
 * Mock web server for Node.js runtime environment
 *
 * @param {number} port
 * @returns {Properties}
 *
 * @author Stefan Schnell <mail@stefan-schnell.de>
 * @license MIT
 * @version 0.1.0
 */

exports.handler = function(context, inputs, callback) {

  const http = require("node:http");
  const process = require("node:process");

  // Returns the first network interface local IP address
  const networkInterfaces = require("os").networkInterfaces();

  let ipAddress = null;

  Object.keys(networkInterfaces).forEach( networkInterface => {
    if (networkInterface.toLowerCase().startsWith("eth")) {
      networkInterfaces[networkInterface].forEach( attributes => {
        if (attributes.family === "IPv4") {
          ipAddress = attributes.address;
        }
      });
    }
  });

  if (ipAddress !== null) {

    // Checks if IP address is IPv4
    let isIPv4 = false;
    let ipv4 = /(?:\d{1,3}\.){3}\d{1,3}/g;
    if (ipAddress.match(ipv4) !== null) {
      isIPv4 = true;
    }

    if (isIPv4) {
      console.log("IPv4Address: " + ipAddress);
    } else {
      console.log("IPv6Address: " + ipAddress);
    }

    // Starts web server
    const server = http.createServer((request, response) => {
      console.log("Request received");
      response.statusCode = 200;

      switch (request.url) {

        case "/end" :
          response.setHeader("Content-Type", "text/plain");
          response.end('{"result": "end"}');
          request.connection.end();
          request.connection.destroy();
          server.close();
          console.log("Server terminated");
          break;

        default :
          response.setHeader("Content-Type", "text/plain");
          response.end('{"result": "Hello World"}');
          break;

      }

    });

    const hostname = ipAddress;

    server.listen(inputs.port, hostname, () => {
      if (isIPv4) {
        console.log(
          "Server running at http://" + hostname + ":" +
          inputs.port + "/"
        );
      } else {
        console.log(
          "Server running at http://[" + hostname + "]:" +
          inputs.port + "/"
        );
      }
    });

  }

  callback(null, {status: "done"});

};

When the web server is started, the IP address is displayed in the log window.
And when a request is executed, this is also displayed in the log window.

vcf automation node.js runtime environment with mock web server
Once the web server has been started, it is available to the entire Aria Automation environment. Requests can be executed against it and the programmed response is delivered.

Node.js - Web Client

The following code is a web client, also based on Node.js. It can be used to execute a request, so that Hello World is returned and displayed. Also the web server can be terminated, via the Action parameter by specifying end. The IP address is also detected automatically here. The web client is simply created as another action of the Node.js runtime environment.

/**
 * Web client for Node.js runtime environment for mock web server
 *
 * @param {number} port
 * @param {string} action - Optional
 * @returns {Properties}
 *
 * @author Stefan Schnell 
 * @license MIT
 * @version 0.1.0
 */

exports.handler = function(context, inputs, callback) {

  const http = require("node:http");
  const process = require("node:process");

  // Returns the first network interface local IP address
  const networkInterfaces = require("os").networkInterfaces();

  let ipAddress = null;

  Object.keys(networkInterfaces).forEach( networkInterface => {
    if (networkInterface.toLowerCase().startsWith("eth")) {
      networkInterfaces[networkInterface].forEach( attributes => {
        if (attributes.family === "IPv4") {
          ipAddress = attributes.address;
        }
      });
    }
  });

  if (ipAddress !== null) {

    const url = "http://" + ipAddress + ":" + String(inputs.port);

    switch (inputs.action) {

      case undefined: case "":

        http.get(url, (response) => {
          let data = "";
          response.on("data", (chunk) => {
            data += chunk;
          });
          response.on("end", () => {
            console.log("HTTP Get: " + data);
          });
  
        }).on("error", (err) => {
          console.log("Error: " + err.message);
        });

        break;

      case "end":

        http.get(url + "/end", (response) => {
          let data = "";
          response.on("data", (chunk) => {
            data += chunk;
          });
          response.on("end", () => {
            console.log("HTTP Get: " + data);
          });
        }).on("error", (err) => {
          console.log("Error: " + err.message);
        });

        break;

      default:

        break;

    }

  }

  callback(undefined, {status: "done"});

};

If the Web Client is executed without action parameter, only specifying the port, Hello World is returned.

vcf automation node.js runtime environment with web client for mock web server
This example already shows that different instances of Node.js actions can communicate with each other via http.

PowerShell - Web Client

The following code is the same web client as above, but in PowerShell.

<#
 # Web client for PowerShell runtime environment for mock web server
 #
 # @param {number} port
 # @param {string} action - Optional
 # @returns {Properties}
 #
 # @author Stefan Schnell 
 # @license MIT
 # @version 0.1.0
 #>

function Handler($context, $inputs) {

  try {

    $ipAddress = $null;

    [System.Net.NetworkInformation.NetworkInterface[]]$networkInterfaces =
      [System.Net.NetworkInformation.NetworkInterface]::`
      GetAllNetworkInterfaces();
    forEach ($networkInterface in $networkInterfaces) {
      if ($networkInterface.name.toLower().startsWith("eth")) {
        [System.Net.NetworkInformation.IPInterfaceProperties]`
          $networkIPProperties = $networkInterface.GetIPProperties();
        forEach ($address in $networkIPProperties.UnicastAddresses) {
          if ($address.Address.AddressFamily -eq 
              [System.Net.Sockets.AddressFamily]::InterNetwork) {
            $ipAddress = $address.Address.toString();
          }
        }
      }
    }

    if ($ipAddress -ne $null) {

      switch ($inputs.action) {

        {($_ -eq "") -or ($_ -eq $null)} {
          $uri = "http://" + $ipAddress.toString() + ":" + $inputs.port;
          break;
        }

        "end" {
          $uri = "http://" + $ipAddress.toString() + ":" +
            $inputs.port + "/end";
          break;
        }

        default {

          break;
        }

      }

      $responseData = Invoke-RestMethod -Method "GET" -Uri $uri;

      $output = @{status = "done"; response = $responseData};
      return $output;

    }

  } catch {
    Write-Host "Exception: $($_.Exception)";
  }

}

vcf automation powershell runtime environment with web client for mock web server
This example shows that different instances of different runtime environments, in this case a PowerShell action, can communicate with each other via http.

Python - WebClient - Terminate Mock Web Server

The following Python code is also a web client. This example shows how the web server can be terminated with a call to the Python runtime environment.

"""
Example how to terminate mock web server via Python

@param {number} port
@returns {Properties}

@author Stefan Schnell <mail@stefan-schnell.de>
@license MIT
@version 0.2.0
"""

import socket
import fcntl
import struct
import json
from urllib.request import Request, urlopen

def handler(context, inputs):

    _socket = socket.socket()
    ipAddress = socket.inet_ntoa(
      fcntl.ioctl(
          _socket.fileno(),
          0x8915,  # Linux SIOCGIFADDR
          struct.pack('256s', bytes('eth0'[:15], 'utf-8'))
      )[20:24]
    )

    httpRequest = Request(
       url = "http://" + ipAddress + ":" + str(inputs["port"]) + "/end",
       method = "GET"
    )

    with urlopen(httpRequest) as response:
        print(response.read().decode())

    outputs = {
        "status": "done"
    };

    return outputs

vcf automation python runtime environment with web client to terminate mock web server
Here the log window of the Node.js mock web server. It is terminated after it has received the request from the Python action.

vcf automation node.js runtime environment log window with the result of the python web client to terminate mock web server

JavaScript - isHostReachable and getContent

Last but not least two examples of calling the web server from the JavaScript runtime environment.

The isHostReachable method of the System object can be used to check whether the web server can be reached.

System.log(HostOrIP);

var result = System.isHostReachable(HostOrIP);
if (result) {
  System.log("Host is reachable");
} else {
  System.log("Host is not reachable");
}

vcf automation javascript runtime environment with the result of a request via ishostreachable to the mock web server
A GET request is executed with the getContent method of the URL object. Invoking this method returns Hello World as expected.

uri = "http://10.244.0.221:3000/";
System.log(uri);

var url = new URL(uri);
var result = url.getContent();
System.log(result);

vcf automation javascript runtime environment with the result of a request via getcontent to the mock web server

Conclusion

As we can see, a web server can be created and used within the Aria Automation environment very easily using on-board resources. Communication and control between the different runtime environments is possible without any problems. As shown in this example, Node.js can "talk" to the Python, PowerShell and JavaScript runtime environment, and this is of course also possible vice-versa. This approach allows us to combine the features of the different runtime environments of Aria Automation with their different programming languages and their specific possibilities.