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:
- The IP address is detected automatically.
- If /end is specified as the path, the execution of the Mock Web Server is terminated.
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.
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.
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)";
}
}
|
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.3.0
"""
import socket
import json
from urllib.request import Request, urlopen
def handler(context, inputs):
ipAddress = socket.gethostbyname(
socket.gethostname()
)
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
|
Here the log window of the Node.js mock web server. It is terminated after it has received the request from the Python action.
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");
}
|
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);
|
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.