By Sai Sarath Chandra, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud's incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.
In the previous tutorial, we have created function in Alibaba Cloud Function Compute console. In this tutorial we will create a web page like below
We will also create a functionality where the web app can upload a file to Object Storage Service (OSS) bucket and also, we can invoke the Alibaba Cloud Function Compute console directly using NodeJS SDK.
The below is what we are trying to achieve:
We have created and tested the OSS Bucket and the function in function compute in last part. Now we are just trying to create web page and add functionalities
We will achieve this in three simple steps:
The whole code is available at https://github.com/saichandu415/NodeJS_FunctionComputeDemo/tree/master/client
The whole front-end logic is written inside an index.html file. We used materialize CSS for bootstrapping.
There are certain building blocks for the UI,
<div class="row">
<div class="input-field col s12">
<input id="email" type="email" class="validate">
<label for="email">Email ID</label>
</div>
</div>
The above code snippet generates an input field along with the validation and the attribute 'type' specifies which type of input field we intended to. All the HTML5 fields are available.
<div class="row valign-wrapper">
<div class="col s9">
<h5>Do you want a mail to be sent with all the information?</h5>
</div>
<div class="col s3">
<div class="switch">
<label>
Off
<input id="mailSwitch" type="checkbox">
<span class="lever"></span>
On
</label>
</div>
</div>
</div>
The above code snippet creates a switch like below beside a text. The key thing to notice here is to use the 'valign-wrapper' which more web developers tend to do the vertical alignment using the css properties but the materialize css provides a ready to use css class to ease the development.
<div id="modal1" class="modal">
<div class="modal-content">
<h4>File uploaded and function triggered</h4>
<p>Find the output below</p>
<p id="output"></p>
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn-flat">Close</a>
</div>
</div>
The above code snippet helps us in displaying the information in a separate modal as this helps us in maintaining the single page structure, yet display the information required.
We also have a custom Javascript inside the html file for all the operations. The custom script is primarily calling the REST API's and propagating the response back to the UI.
One endpoint we are calling here does the task of sending the file to the OSS,
function uploadFile() {
var request = {
filepath: ''
};
request.filepath = document.getElementById('filepath').value;
console.log(request);
fetch('http://localhost:8080/api/todos', {
method: "POST",
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify(request)
})
.then((res) => res.json())
.then(function (data) {
console.log(data);
var instance = M.Modal.getInstance(document.getElementById('modal1'));
document.getElementById('output').innerText = JSON.stringify(data, null, 2);
instance.open();
return data;
});
}
Here we are accomplishing a number of tasks:
function invokeFunc(){
var request = {
firstname: '',
message: 'This should capitalize',
doMail: true,
toMail: ''
};
request.firstname = document.getElementById('first_name').value;
request.doMail = document.getElementById('mailSwitch').checked;
request.toMail = document.getElementById('email').value;
console.log(request);
fetch('http://localhost:8080/api/invoke', {
method: "POST",
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify(request)
})
.then((res) => res.json())
.then(function (data) {
console.log(data);
M.toast({html: "Function Invoked : "+data.message, classes: 'rounded'});
return data;
});
}
In the above function, the endpoint which we are calling does the work of invoking the function of the function compute directly. After getting the response, it converts to JSON and displays it as a toast message in the UI.
There are a few things happening here:
Now, we will discuss about the endpoints which we used and what logic do they contain. Before we examine that, you need to make sure all the necessary information is being filled in the keyinfo.json under /config folder.
{
"accessKeyId": "<YOUR ACCESS KEY ID>",
"accessKeySecret": "<YOUR ACCESS KEY SECRET>",
"bucket": "<YOUR BUCKET NAME>",
"oss_region": "oss-<YOUR REGION NAME>",
"accountId": "<YOUR ACCOUNT ID WITHOUT QUOTES>",
"region": "<YOUR REGION NAME>",
"fc_serviceName": "<YOUR SERVERLESS SERVICE NAME>",
"fc_funcName": "<YOUR SERVERLESS FUNCTION NAME>"
}
I believe all the information here are available in the console.
Let's look into how endpoints are created and what do they contain.
Navigate to client/app/routes.js which is the relevant file containing the endpoints,
var alioss = require('ali-oss');
var fc = require('@alicloud/fc');
var keyInfo = require('../config/keyInfo.json');
The key thing to functionality here is the SDK's.
ali-oss : It is the official NodeJS SDK for the OSS (Object Storage Service), using which we are going to upload the file directly to OSS>
@alicoud/fc : This is the official NodeJS SDK for the (fc) Function Compute, using which we are invoking the function.
keyInfo.json: will contain all the keys required for the Alibaba cloud SDK's.
const store = alioss({
accessKeyId: keyInfo.accessKeyId,
accessKeySecret: keyInfo.accessKeySecret,
bucket: keyInfo.bucket,
region: keyInfo.oss_region
});
The above code snippet is written in at the file level, so that the initiation happens at the start of the server which will highlight any issues that might cause due to the accesskeys. The above snippet creates an authenticated store object for OSS SDK to do further file related operations.
var client = new fc(keyInfo.accountId, {
accessKeyID: keyInfo.accessKeyId,
accessKeySecret: keyInfo.accessKeySecret,
region: keyInfo.region,
timeout: 30000 // Request timeout in milliseconds, default is 10s
});
The above is similar to the OSS store object but this is for Function Compute. This required the timeout in milliseconds to specify till when we can wait for the output of the function.
Uploading file to OSS:
app.post('/api/todos', function (req, res) {
console.log(req.body);
var filepath = '/Users/sarathchandrap/Desktop/testData/' + req.body.filepath;
store.put(req.body.filepath, filepath).then((result) => {
console.log(result);
res.send(result);
});
});
The 4 lines of code above pushes a file onto the OSS with a given name and triggers a function in the Function Compute automatically. If you realize, we are using 'store.put' to upload the file to OSS.
module.exports = function (app) {
app.post('/api/invoke', function (req, res) {
var invokeReq = {
firstname: req.body.firstname,
message: req.body.message,
doMail: req.body.doMail,
toMail: req.body.toMail
}
var funcRes = {
message: ''
}
client.invokeFunction(serviceName, funcName, JSON.stringify(invokeReq)).then(function(response){
res.setHeader('Content-Type', 'application/json');
funcRes.message = response;
res.send(JSON.stringify(funcRes));
});
});
This function we are constructing the input request using parameters from the request (req.body) and also making a response object with empty information. We invoke the function using the 'client.invokeFunction' along with the serviceName, funcionName and the request.
The code provided in GitHub, particularly the client, consists of the rest API too. We can also deploy the code to the ECS instance thereby making it available over the internet. If you are planning to do so, you can find the REST API related port values under 'app/routes.js' and webapp related settings at 'server.js'.
Instructions to run the client application:
You get the following message
App listening on port 8080
Go ahead and access the app at localhost:8080
Successfully, we have created the webapp and triggered the function by uploading OSS file and also invoking the function directly using the NodeJS SDK.
Bootstrapping Function Compute for Web Using NodeJS SDK: Part 1
How to Develop Web Applications on Alibaba Cloud with Django Framework
2,599 posts | 762 followers
FollowAlibaba Clouder - December 7, 2018
Alibaba Clouder - May 6, 2019
Alibaba Cloud Serverless - August 21, 2019
Alibaba Clouder - November 20, 2018
Alibaba Cloud Serverless - August 21, 2019
afzaalvirgoboy - June 17, 2020
2,599 posts | 762 followers
FollowElastic and secure virtual cloud servers to cater all your cloud hosting needs.
Learn MoreAn encrypted and secure cloud storage service which stores, processes and accesses massive amounts of data from anywhere in the world
Learn MoreAlibaba Cloud Function Compute is a fully-managed event-driven compute service. It allows you to focus on writing and uploading code without the need to manage infrastructure such as servers.
Learn MoreMore Posts by Alibaba Clouder