Tutorials
edgeEngine Serverless APIs
Traditional backend development requires developers to think about how to scale, maintain and operate a server. To simplify the process, mimik provides a serverless environment for edge microservices to use at runtime. edgeEngine takes care of deployment and all concerns related to servers. Developers only need to design the processing of HTTP requests and responses. That is why it is called serverless programming.
To start with, you supply a callback function and assign it to mimikModule.exports. The callback function must have the following arguments:
context request response
These arguments give you full control over HTTP requests and responses. The context argument passes mimik’s serverless programming environment.
import Router from 'router';
const app = Router({ mergeParams: true });
mimikModule.exports = (context, request, response) => {
global.context = context;
app(request, response, (e) => {
request.end(JSON.stringify({ code: e ? 400 : 404, message: e || 'Not Found' }));
});
};
app.get('/', (request, response) => {
response.end('Hello World!');
});
context
Description
Type
object
Property | Type | Description |
---|---|---|
env | object | This object contains environment variables passed on to a container on initialization.
|
storage | object | Please refer to the documentation below on storage APIs. |
http | object | Please refer to the documentation below on http client APIs.
|
edge | object | Please refer to the documentation below on edge APIs. |
Description
Type
object
Property | Type | Description |
---|---|---|
url | string | The url of the request. |
method | string | The HTTP method of the request, such as GET, POST, DELETE, PUT, etc.
|
authorization | string | The HTTP header, such as the Authorization Header.
|
body | string | If the content-type is application/json of the client, this will be the body of the POST or PUT request.
|
handleFormRequest | function | This function is used to handle HTTP POST with content type ‘multipart/form-data’. The function takes an object formRequestOption from the developer to generate a list of required callbacks. See below for more detail.
|
request.handleFormRequest(formRequestOption)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
formRequestOption | object | This object passes the callback function required by request.handleFormRequest() to handle the HTTP Form POST.
|
Example Code
app.post('/form', (request, response) => {
const metadata = "";
const file = {};
req.handleFormRequest({
found: (key, filename) => {
let formRequestToDo = {
action: 'skip'
};
if (key === 'metadata') {
formRequestToDo = {
action: 'get'
};
} else if (key === 'file') {
file.filename = filename;
formRequestToDo = {
action: 'store',
path: 'new-filename'
};
} else {
formRequestToDo = {
action: 'abort'
}
}
return formRequestToDo ;
},
get: (key, value) => {
metadataBuf = metadata.concat(value);
},
store: (path, size) => {
file.path = path;
file.size = size;
},
});
response.end(value);
});
Description
This object passes the required function required by request.handleFormRequest()
to handle the HTTP Form POST.
Type
object
Property | Type | Description |
---|---|---|
found | function | This function callback is called whenever a new key is encountered. You must return a formRequestToDo to indicate what to do with the key. Please refer to formRequestToDo.action and formRequestToDo.path.
|
get | function | This function callback is called when you indicate the method to get the data using a key. The value of the key is returned as a string.
|
store | function | This function callback is called when you indicate the method to store data with a specific path.
|
formRequestOption.found(key, filename)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
key | string | The key of the form element.
|
filename | string | The name of the file to store.
|
Example
app.post('/form', (request, response) => {
const metadata = "";
const file = {};
req.handleFormRequest({
found: (key, filename) => {
if (key === 'file') {
file.filename = filename;
formRequestToDo = {
action: 'store',
path: 'new-filename'
};
}
return formRequestToDo ;
}
});
response.end(value);
});
formRequestOption.found(key, filename)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
key | string | The key of the form element.
|
filename | string | The value of the form element corresponding to the key.
|
Example Code
app.post('/form', (request, response) => {
const metadata = "";
const file = {};
req.handleFormRequest({
get: (key, value) => {
metadataBuf = metadata.concat(value);
}
});
response.end(value);
});
formRequestOption.store(path, size)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
path | string | The file path of the form element to store.
|
size | string | The value of the form element corresponding to the key.
|
Example Code
app.post('/form', (request, response) => {
const metadata = "";
const file = {};
req.handleFormRequest({
store: (path, size) => {
file.path = path;
file.size = size;
}
});
response.end(value);
});
Description
Type
object
Property | Type | Description |
---|---|---|
action | string | The following actions are available:
· abort: this will abort the entire form request.
· skip: this will skip the current key of the form request.
· store: this will handle the form request using the store function provided in formRequestOption.
· get: this will handle the form request using the get function provided in formRequestOption. |
path | string | If formRequestToDo.action is store, one needs to know where to store the file. formRequestToDo.path is the path of the file.
|
Description
This class represents the server HTTP response object, similar to a Express.js HTTP server response object.
Type
object
Property | Type | Description |
---|---|---|
statusCode | integer | The HTTP response code. the default is 200.
|
end | function | Send back the response in string.
|
writeMimeFile | function | Send back the response as mime file.
|
response.end(body)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
body | string | The response body, which must be a string.
|
Example Code
app.get('/', (request, response) => {
response.statusCode = 200;
response.end('<h1>Hello World!</h1>');
});
response.writeMimeFile(filePath, mimeType)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
filePath | string | The path of the file that response.writeMimeFile() wants to return
|
mimeType | string | The file type of the return file. The default is application/json
|
Example Code
app.get('/', (request, response) => {
response.statusCode = 200;
const filePath = '/home/usr/example.jpeg';
response.writeMimeFile(filepath, 'image/jpeg');
});
Description
In order for an edge microservice to store something on a device, mimik provides a light-weight key-value database based on SQLite.
Type
object
Property | Type | Description |
---|---|---|
getItem | function | This function gets the data from the database by querying using the data’s key.
|
setItem | function | This function sets the value of the data using a key in the database.
|
eachItem | function | This function iterates through the database and makes a callback for each database record.
|
removeItem | function | This function removes a data entry from the database using its key.
|
saveFile | function | This function iterates through the database and makes a callback for each database record.
|
deleteFile | function | This function deletes the file with corresponding filename.
|
context.storage.getItem(key)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
key | string | Get value from the database by querying using a key.
|
Return Type
string
Example Code
app.get('/', (request, response) => {
const value = context.storage.getItem('key');
response.end(value);
});
context.storage.setItem(key, value)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
key | string | Get a value from the database by querying using its key.
|
value | string | Set a value in the database using its key.
|
Example Code
app.post('/form', (request, response) => {
const { name } = JSON.parse(request.body);
context.storage.setItem('name', name);
response.end('value stored successfully.');
});
context.storage.eachItem(callback(key, value))
Type
function
Arguments
Argument | Type | Description |
---|---|---|
callback(key, value) | function | A callback for handling each item in a database with the given key and value.
|
Example Code
app.get('/', (request, response) => {
context.storage.eachItem((key, value) => {
// do something....
});
response.end('done');
});
context.storage.removeItem(key)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
key | string | Remove an item from a database using its key.
|
Example Code
app.delete('/form', (request, response) => {
context.storage.removeItem('name');
response.end('item remove successfully.');
});
context.storage.saveFile(fileName, base64EncodedString)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
fileName | string | The name of the file.
|
base64EncodedString | string | Save a file in a database with its base64Encoded binary data.
|
Example Code
app.post('/file', (request, response) => {
const base64 = '..........';
const fileName = 'base64.jpeg';
context.storage.saveFile(fileName, base64);
response.end('item save successfully.');
});
context.storage.deleteFile(fileName)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
fileName | string | The name of the file.
|
base64EncodedString | string | Delete the file’s base64Encoded binary data.
|
Example Code
app.delete('/file', (request, response) => {
const fileName = 'base64.jpeg';
context.storage.deleteFile(fileName);
response.end('item delete successfully.');
});
Description
In order for an edge microservice to make a HTTP request to another edge microservice or mimik’s backend, mimik provides a built-in HTTP request client for HTTP communication.
Type
object
Property | Type | Description |
---|---|---|
request | function | This function takes the httpClientOption and parses it as an instance of a HTTP client interface.
|
context.http.request(httpClientOption)
Type
function
Arguments
Property | Type | Description |
---|---|---|
httpClientOption | object | These are the available HTTP request configuration options for making requests within the edge microservice context.
|
Example Code
app.post('/data', (request, response) => {
context.http.request(({
type: 'POST',
data: '{}',
url: 'http://www.example.com/data',
authorization: 'Bearer token',
success: (result) => {
response.end(result.data);
},
error: (err) => {
console.log(err);
}
}));
});
Description
Type
object
Property | Type | Description |
---|---|---|
type | string | The HTTP method of the request, such as GET, POST, DELETE, PUT etc.
|
data | string | If the HTTP method is POST or PUT or PATCH, the data is the body of the method.
|
url | string | The URL of the HTTP request.
|
authorization | string | The HTTP authorization header of the request.
|
success | function | This is the success callback function.
|
error | function | This is the error callback function.
|
httpClientOption.success(result)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
result | string | Parses the result of the HTTP request to the callback function.
|
Example Code
app.get('/data', (request, response) => {
context.http.request(({
type: 'get',
data: '{}',
url: 'http://www.example.com/data',
authorization: 'Bearer token',
success: (result) => {
response.end(result.data);
}
}));
});
httpClientOption.error(result)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
error | string | Parses the error of HTTP request to the callback function
|
app.get('/ping', (request, response) => {
context.http.request(({
type: 'get',
data: '{}',
url: 'http://www.example.com/ping',
authorization: '',
error: (error) => {
response.end('Website is offline!');
}
}));
});
Description
In order for an edge node to securely receive sensitive information about the cluster and back-end tunneling information, mimik provides functions to decrypt the encrypted messages and making requests to the back-end to create a private tunnel (which is a BEP).
Type
object
Property | Type | Description |
---|---|---|
decryptEncryptedNodesJson | function | This function decrypts the sensitive information about cluster and cloud backend receive by the edgeEngine from other edge nodes.
|
requestBep | function | This function will request a BEP tunnel from edgeEngine. If a BEP has not already been created, this will create a new BEP. If a BEP has already been created, this will just return the existing BEP.
|
context.edge.decryptEncryptedNodesJson(decryptNodesOption)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
decryptNodesOption | object | These are the available decrypting node message configuration options for extracting sensitive information from clusters.
|
Example Code
app.get('/localDevices', (request, response) => {
context.http.request(({
url: `http://127.0.0.1:8083/mds/v1/nodes?clusters=linkLocal`,
success: (result) => {
const nodes = JSON.parse(result.data);
const data = JSON.stringify(nodes.data);
context.edge.decryptEncryptedNodesJson({
type: 'local',
data: encryptedJson,
success: (result) => {
response.end(result.data);
},
error: (err) => {
console.log(err.message);
}
});
},
error: (err) => {
console.log(err.message);
}
}));
});
context.edge.requestBep(requestBepOption)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
requestBepOption | object | These are the available BEP request configuration options for receiving a private communication tunnel.
|
app.get('/localDevices', (request, response) => {
context.edge.requestBep({
success: (result) => {
console.log(result.data);
},
error: (err) => {
console.log(new Error(err.message));
}
});
// ...
});
Description
These are the available decrypting node message configuration options for extracting sensitive information from clusters.
Type
object
Property | Type | Description |
---|---|---|
type | string | The type indicates that the data to decode is either ‘account’ or ‘local’. If the data is obtained from an account cluster, one should use ‘account’. Anything else should use ‘local’.
|
token | string | The edge token that you obtained through mimik’s OpenID.
|
data | string | The data JSON that you got from the GET /nodes that you would like to decode.
|
success | function | This is the success callback function.
|
error | function | This is the error callback function.
|
decryptNodesOption.success(result)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
result | string | Parses the result of decryption to the callback function.
|
Example Code
app.get('/localDevices', (request, response) => {
context.http.request(({
url: 'http://127.0.0.1:8083/mds/v1/nodes?clusters=linkLocal',
success: function(r) {
if (!request.authorization) {
response.status = 403;
response.end(JSON.stringify({ 'msg': 'missing bearer token' }, 2, null));
return;
}
const authorization = request.authorization.split(' ');
if (authorization.length < 2) {
response.status = 403;
response.end(JSON.stringify({ 'msg': 'missing bearer token' }, 2, null));
return;
}
const token = authorization[1];
const nodes = JSON.parse(r.data);
const data = JSON.stringify(nodes.data);
context.edge.decryptEncryptedNodesJson({
type: 'local',
data,
token,
success: function(result) { // success option
response.end(JSON.stringify(JSON.parse(result.data), null, 2));
},
error: function(err) {
response.end(err.message);
}
});
},
error: function(err) {
response.end(err.message);
}
}));
});
decryptNodesOption.error(result)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
error | string | Parses the error of decryption to the callback function.
|
Example Code
app.get('/localDevices', (request, response) => {
context.http.request(({
url: 'http://127.0.0.1:8083/mds/v1/nodes?clusters=linkLocal',
success: function(r) {
if (!request.authorization) {
response.status = 403;
response.end(JSON.stringify({ 'msg': 'missing bearer token' }, 2, null));
return;
}
const authorization = request.authorization.split(' ');
if (authorization.length < 2) {
response.status = 403;
response.end(JSON.stringify({ 'msg': 'missing bearer token' }, 2, null));
return;
}
const token = authorization[1];
const nodes = JSON.parse(r.data);
const data = JSON.stringify(nodes.data);
context.edge.decryptEncryptedNodesJson({
type: 'local',
data,
token,
success: function(result) {
response.end(JSON.stringify(JSON.parse(result.data), null, 2));
},
error: function(err) { // error option
response.end(err.message);
}
});
},
error: function(err) {
response.end(err.message);
}
}));
});
Description
These are the available BEP request configuration options for receiving a private communication tunnel.
Type
object
Property | Type | Description |
---|---|---|
success | function | This is the success callback function.
|
error | function | This is the error callback function.
|
requestBepOption.success(result)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
result | string | Parses the result of the BEP request to the callback function.
|
Example Code
app.get('/localDevices', (request, response) => {
context.edge.requestBep({
success: (result) => {
console.log(result.data);
}
});
// ...
});
requestBepOption.error(error)
Type
function
Arguments
Argument | Type | Description |
---|---|---|
error | string | Parses the error from the BEP request to the callback function.
|
Example Code
app.get('/bep', (request, response) => {
context.edge.requestBep({
error: (error) => {
response.end('Cannot get BEP!');
}
});
// ...
});