how call a azure function from a html? - azure

I need the following. Create an azure function that generates qr code. Until then I found a tutorial. HttpTrigger, in javascript, with node -qrcode library
But I need to call this function in a simple html/css I made. how to make?
The azure function looks like this:
//require the module qrcode
const QRCode = require('qrcode');
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if(req.query.text) {
let code;
try {
code = await QRCode.toDataURL(req.query.text);
} catch (err) {
context.log.error('ERROR', err);
throw err;
}
if (code) {
context.res = {
body: code
}
} else {
context.res = {
body: "Error: QR Code rendering error",
status: 400
}
}
} else {
context.res = {
body: "Error: Missing query string text",
status: 400
}
}
}

After you publish your function, you should get the Function URL from the Azure portal, and then make an HTTP call from inside your html page(for example using jQuery, ajax etc). In your function.json, you should have mentioned which HTTP methods your function supports , example GET, POST. Refer https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-node

Related

How to call Firebase onRequest Cloud Function?

I have the following addEventToCalendar cloud function :
const { google } = require("googleapis");
const calendar = google.calendar("v3");
//const functions = require('firebase-functions');
const googleCredentials = require("./credentials.json");
const OAuth2 = google.auth.OAuth2;
const ERROR_RESPONSE = {
status: "500",
message: "There was an error adding an event to your Google calendar",
};
const TIME_ZONE = "EST";
const addEvent = (event, auth) => {
return new Promise(function (resolve, reject) {
calendar.events.insert(
{
auth: auth,
calendarId: "primary",
resource: {
summary: event.eventName,
description: event.description,
start: {
dateTime: event.startTime,
timeZone: TIME_ZONE,
},
end: {
dateTime: event.endTime,
timeZone: TIME_ZONE,
},
},
},
(err, res) => {
if (err) {
console.log("Rejecting because of error");
reject(err);
}
console.log("Request successful");
resolve(res.data);
}
);
});
}
exports.addEventToCalendar = functions.https.onRequest((request, response) => {
const eventData = {
eventName: request.body.eventName,
description: request.body.description,
startTime: request.body.startTime,
endTime: request.body.endTime,
};
console.log("Event Data: ", eventData);
const oAuth2Client = new OAuth2(
googleCredentials.web.client_id,
googleCredentials.web.client_secret,
googleCredentials.web.redirect_uris[0]
);
oAuth2Client.setCredentials({
refresh_token: googleCredentials.refresh_token,
});
addEvent(eventData, oAuth2Client)
.then((data) => {
response.status(200).send(data);
return;
})
.catch((err) => {
console.error("Error adding event: " + err.message);
response.status(500).send(ERROR_RESPONSE);
return;
});
});
URL looks like this : http://localhost:5001/prototype-dev-fadd5/us-central1/addEventToCalendar
How do I call this by passing the following data?
{
"eventName": "Firebase Event",
"description": "This is a sample description",
"startTime": "2018-12-01T10:00:00",
"endTime": "2018-12-01T13:00:00"
)
When I say call, it implies 2 things:
Call from a browser just to test it.
Call it from another firebase cloud function which runs on a trigger.
To call it from a browser, you can call it using XHR:
const data = {
eventName: 'Firebase Event',
description: 'This is a sample description',
startTime: '2018-12-01T10:00:00',
endTime: '2018-12-01T13:00:00'
}
fetch('http://localhost:5001/prototype-dev-fadd5/us-central1/addEventToCalendar', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then(response => {
// ...
}).catch(error => {
// ...
});
To call it from another Cloud Function, I'd suggest exporting the addEvent function so you can import and use it elsewhere.
I'd also move the creation of the oAuth2Client object over to the addEvent() function so that you don't have to create an oAuth client before calling the addEvent() function.
If you can't re-use the addEvent() function because the two Cloud Functions live in separate projects and you can't share code between them, I'd call the function through XHR using a tool like Axios or node-fetch.
I know the tutorial you are using.
There are two good ways to test it:
Google Cloud Function Console, Testing tab
Postman
And for using it, I can think of 3 good ways to actually use it.
fetch Javascript from the frontend
Callable Firebase Functions from the frontend
export import to use from the backend.
Testing - Google Cloud Functions Console.
https://console.cloud.google.com/functions/
Testing - Postman
To test you can also use Postman.
Create a POST request with the URL of your function.
Then set the body to raw, with the type set to JSON. Once that is all setup, hit send and the response will show up if you did everything correctly.
See this image on where to click in Postman.
Using - fetch
Fetch provides a
global fetch() method that provides an easy, logical way to fetch
resources asynchronously across the network.
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
And luckily, Postman will write the fetch code for you.
Click on the Code tab, and select Javascript - Fetch from the dropdown.
Using - Callable Functions
Callable Functions are functions you can call directly from your Javascript on the front end. They are explained here. https://firebase.google.com/docs/functions/callable
Biggest difference is instead of using
functions.https.onRequest
in your function declaration, you use:
functions.https.onCall
Using - export to use in Node.js on your server
If you want to be able to call a function directly on your Node.js server, aka your Firebase functions, if the function is in the same file, you call it like any other javascript file.
function normalFunction() {
//do work
return data;
}
exports.addEventToCalendar = functions.https.onRequest((request, response) => {
let data = normalFunction();
response.send(data);
}
You can put whatever you want in the normalFunction and call it where ever you want. Just make sure to use a promise, or await if it is doing something on a server etc.
If you want to use normalFunction from a different file, you would need to use export. https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
Firebase has a good doc on how you can organize multiple files here https://firebase.google.com/docs/functions/organize-functions

Timeout Azure Function if trigger other azure function

I am new Azure function. I want to call the Azure function which will trigger another Azure function. I have written bellow code but its giving me timeout. The code written in node js.
Please suggest what to do.
module.exports = async function (context, req, callback) {
UtilityAccountNumber=req.body.UtilityAccountNumber.split(',');
if(UtilityAccountNumber=='' || typeof UtilityAccountNumber==='undefined' || !(Array.isArray(UtilityAccountNumber) && UtilityAccountNumber.length) ){
response={
status: 0,
message:"Please provide utility acccount number."
};
else{
if(UtilityAccountNumber.length){
for(let accountNo of UtilityAccountNumber){
try
{
var options = {
host: process.env.API_HOST,
port: process.env.PORT,
path: '/api/'+process.env.WEBSCRAPERMASTER,
method: 'POST'
};
var myreq = http.request(options, function(res) {
});
myreq.end();
}
catch (ex) // if failed
{
await logHTTPErrorResponse(ex, huId);
console.error(ex);
}
}
}
}
context.res = {
status: 200,
body: response
};
};
Your code logic may be stuck at some point, so it gives you timeout.(Azure function has a default timeout limit.) I think the function chain of azure durable function fully meets your requirements, and you are using nodejs, so azure durable function is supported.
Please have a look of this:
https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-sequence?tabs=javascript

Simple Azure retrieveEntity is not executed at all

This very simple thing does not work for me even though I have practically copy + pasted the example code from here:
https://github.com/Azure/azure-storage-node
It seems that tableService.retrieveEntity never fires at all? The context.log does not print anything. I get a status 200 with no body but this is because that is Azure's default.
It is the same problem if I write a query and use the queryEntities-method as well.
I write these things in the Azure Portal for simplicity's sake.
This is my code:
var azure = require('azure-storage');
module.exports = async function (context, req) {
var tableService = azure.createTableService('myTable', 'GoYVMvN+SXRJhzVERIYWFu6k0/DkZINIerS+YpwmQVy3ppPFJ+8bTavfisHJvsNbo5hjgpw40bWv8XXXXXXXXX==');
tableService.retrieveEntity('myList', 'MyPartitionKey', '1', function(error, result, response) {
context.log("retrieving...")
if(!error){
context.res = {
status: 200,
body: "The entity was retrieved"
}
} else {
context.res = {
status: 500,
body: "The entity was not retrieved"
}
}
});
};

Getting data from API inside a graphQL resolver deployed on Azure node.js function

I am trying to deploy a GraphQL server on node.js platform using Azure functions. I have been able to deploy a basic hello world app.
However, I need to get data from a backend API in the resolver. I am not able to get either fetch or request package to work in Azure functions.
Below is my code:
var { graphql, buildSchema } = require('graphql');
var fetch = require('node-fetch');
var request = require('request');
var schema = buildSchema(`
type Query {
myObject: MyObject
}
type MyObject {
someId (data: String) : String
}
`);
var root = {
myObject: () => {
return {
someId: (args) => {
// Code enters till this point.
// I can see context.info messages from here.
// return "hello"; <--- This works perfectly fine.
return request('http://example.com', function (error, response, body) {
// -----> Code never enters here.
return body;
});
}
}
}
};
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
graphql(schema, req.body, root)
.then(response => {
context.res = {
body: JSON.strigify(response)
};
context.done();
});
};
I have tried using fetch and request modules. But with both of them, I see the same behavior - the response never returns. The request eventually times out after 5 minutes. If instead of fetch or request, I choose to return some dummy value, I see the response getting returned correctly to the query. With fetch, I don't see the then block or the catch block ever executing.
Note: I have tried both http and https URLs in the request URIs but none of them seem to return any data.
Is it an issue with the way I have implemented the fetch/request or is it an issue with Azure functions in general?
Answering my own question:
It seems that node-fetch and request don't actually return promises. Wrapping the request around Promise seems to solve the problem. Something similar to this answer.

AZURE Mobile Service forwarding POST request in insert script of table

I'm trying to use Azure Mobile Service to process / handle GET and POST requests on an empty data table. (really just using the mobile service as a pass through)
As part of this I'm trying to forward the request to another url and receive the response back and return it via mobile service. I've figured out the GET part shown below but I'm having trouble the POST part.
GET Part:(Which works)
function read(query, user, request)
{
var p = request.parameters;
var httpRequest = require('request');
var url = 'http://someURL/'+ p.ssoid;
httpRequest.get(url, function(err, response, body)
{
if (err)
{
request.respond(500, "INTERNAL SERVER ERROR");
}
else
{
request.respond(200,JSON.parse(body) );
}
});
}
Post Code:(Does not work)
function insert(item, user, request)
{
var p = request.parameters;
require('request').post({
uri:'http://someURL/',
headers:{'content-type': 'application/json'},
body:p.body
},function(err,res,body){
if (err)
{
request.respond(500, "INTERNAL SERVER ERROR");
}
else
{
request.respond(200,"Success");
}
});
}
I know the POST requires a body with the post information, but how to I get it to pass forward?
On an insert, the body of the request will be stored in the item argument (assuming you're passing a JSON object). So your function would look something like this:
function insert(item, user, request)
{
var p = request.parameters;
require('request').post({
uri : 'http://someURL/',
headers : {'Content-Type': 'application/json'},
body : item
}, function(err, res, body){
if (err)
{
request.respond(500, "INTERNAL SERVER ERROR");
}
else
{
request.respond(200,"Success");
}
});
}
On a related note, if you're using the mobile service as a simple pass-through, you can also consider using a custom API instead of a table, where you can also apply your logic without having any (empty) table behind it.
function insert(item, user, request)
{
var p = request.parameters;
require('request').post({
uri : 'http://someURL/',
headers : {'Content-Type': 'application/json'},
body : JSON.stringify(item)
}, function(err, res, body){
if (err)
{
request.respond(500, "INTERNAL SERVER ERROR");
}
else
{
request.respond(200,"Success");
}
});
}

Resources