How to call an EasyAPI from an Azure WebJobs? - node.js

In WAMS, Windows Azure Mobile Service, you could easily configure a Schedule Service to call on any custom API that you have. However, how is that same scenario being implemented with Azure Web Jobs in Node ? How can I access the reference to an Azure Mobile Service Client object that I can use to call an EasyAPI Service from a Mobile Apps Module, like:
var client = azure.azureMobile;
azure.invokeApi("customers", {
method: "get"
}).done(function (results) {
console.log('Result:'+results.result);
}, function (error) {
console.log('Error:'+error);
});
Is there any available "azure"-like object that we can use from inside the WebJob code ?

As the Custom APis in Mobile Apps are exposed as RESTful APis, so you can simply implement HTTP requests against your Easy APIs on Mobile Apps. You can try to following code snippet in the webjob.
var http = require("https")
var options = {
host: "<mobileappname>.azurewebsites.net",
path: "/api/easyapi",
headers: {
"ZUMO-API-VERSION": "2.0.0"
}
};
req = http.request(options, (res)=>{
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
req.end();
Any further concern, please feel free to let me know.

Related

Timeout error when calling API from Nodejs

I am calling this public API from my nodejs. I am using system in office enviornment and I have to connect with VPN to accress office url. When I use wifi of my mobile then I can access below API.
https://dummy.restapiexample.com/api/v1/employees
the above is public API. anybody can check.
I have to use https to access API in node because of security reasons. How can i access the API when I am in my office enviornment. I am getting below error.
Error:connect ETIMEDOUT 52.220.246.189:443.
below is the code.
const https = require('https');
https.get('https://dummy.restapiexample.com/api/v1/employees', (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
console.log(data);
});
resp.on('end', () => {
console.log(JSON.parse(data).explanation);
});
console.log("data");
}).on("error", (err) => {
console.log("Error: " + err.message);
});
How can I resolve the same?

How to migrate Managed Azure API Developer Portal(not legacy) Content to new instances

Using scripts https://github.com/Azure/api-management-developer-portal/wiki/Migrate-portal-between-services, I was able to retrieve all definitions and deploy to a new instance, the problem was that only legacy Portal was migrated, new portal was not. How can we migrate the new Developer portal? I couldn't find any settings or reference in the scripts or documentation, I also tried changing the version of the api scripts currently have it as 2018-06-01-preview, but that also failed.
Running the scripts on a mac did not return any results for calls made to the Azure API(not for the capture.js, neither for the generate.js), had to make some changes to the js files and create .sh scripts.
migrate.sh
#!/usr/bin/env bash
#Migrate the content of an API Management portal from one service instance to another - incl. pages, layouts, configuration, media files, etc.
# BEGIN: provide all the required parameters. If your portal is self-hosted, use the storage account connection string from the config.design.json file. If your portal is managed, refer to the documentation for instructions on accessing its storage account connection string.
export source_management_endpoint="< source_service_name >.management.azure-api.net"
export source_access_token="SharedAccessSignature ..."
export source_storage_connection_string="DefaultEndpointsProtocol= ..."
export target_management_endpoint="< target_service_name >.management.azure-api.net"
export target_access_token="SharedAccessSignature..."
export target_storage_connection_string="DefaultEndpointsProtocol=..."
# END: provide all the required parameters.
export data_file="../dist/data.json"
export media_folder="../dist/content"
export media_container="content"
# Quotes are important in the parameters especially in the case of access_tokens, they have spaces in their values, that will throw off the js scripts.
# Capture the content of the source portal (excl. media)
node ./capture "$source_management_endpoint" "$source_access_token" "$data_file"
# Remove all the content of the target portal (incl. media)
node ./cleanup "$target_management_endpoint" "$target_access_token" "$target_storage_connection_string"
# Upload the content of the source portal (excl. media)
node ./generate "$target_management_endpoint" "$target_access_token" "$data_file"
# Download the media files from the source portal
mkdir "$media_folder"
az storage blob download-batch --source "$media_container" --destination "$media_folder" --connection-string "$source_storage_connection_string"
# Upload the media files to the target portal
az storage blob upload-batch --source "$media_folder" --destination "$media_container" --connection-string "$target_storage_connection_string"
#At this point your target API Management service should contain the same content of the portal as the source service. To make the portal of the target service available to visitors, you still need to publish it and, in case of a self-hosted version, host the generated files.
Had to change the request function for capture.js and generate.js, original code is using string to capture payload, changing it to a Buffer Array, solved in my case. Here is the new request
capture.js
async function request(url){
return new Promise((resolve,reject)=>{
const req = https.get(url,options, (res) =>{
let bodyChunks = [];
res.on('data', (chunk)=> {
bodyChunks.push(chunk);
}).on('end', ()=> {
let body = Buffer.concat(bodyChunks);
// console.log('BODY: ' + body);
try {
resolve(JSON.parse(body));
}
catch (e) {
reject(e);
}
})
})
req.on('error', (e)=> {
console.log('ERROR: ' + e.message);
reject(e);
})
req.end();
})
}
generate.js
async function request(url,body){
return new Promise((resolve,reject)=>{
const options = {
port: 443,
method: "PUT",
headers: {
"If-Match": "*",
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(body),
"Authorization": accessToken
}
};
const req = https.request(url,options, (res) =>{
let bodyChunks = [];
res.on('data', (chunk)=> {
bodyChunks.push(chunk);
}).on('end', ()=> {
let data = Buffer.concat(bodyChunks);
// console.log('DATA: ' + data);
try {
resolve(JSON.parse(data));
}
catch (e) {
console.log(url);
reject(e);
}
})
})
req.on('error', (e)=> {
console.log('ERROR: ' + e.message);
reject(e);
});
req.write(body);
req.end();
})
}

Make http request call using Inline Editor in DialogFlow

Below is the function i am calling but every time i am getting below error
Error - MalformedResponse
Failed to parse Dialogflow response into AppResponse because of empty speech response.
$ below is the complete code
function callExternalAPI () {
return new Promise((resolve, reject) => {
let path = 'path';
console.log('API Request: ' + path);
http.get({host: host, path: path}, (res) => {
let body = '';
res.on('data', (d) => { body += d; });
res.on('end', () => {
let response = JSON.parse(body);
let output = 'response';
console.log(output);
resolve(output);
});
res.on('error', (error) => {
console.log(`Error calling the weather API: ${error}`);
reject();
});
});
let intentMap = new Map();
intentMap.set('CardView',callExternalAPI);
agent.handleRequest(intentMap);
});
The inline editor uses Cloud Functions for Firebase. By default, your project is using the Firebase "Spark" plan, which limits network connections to Google services only.
Since the connection is being rejected, the if (err) block is being triggered, and you have not specified a response to be sent back to the user when this happens, so you're getting the "empty speech response" error.
The easiest solution is to upgrade to paid plan, such as the "Blaze" plan, which will require you to register a credit card, but which has a free tier, so you won't be charged for a base level of operations, which generally covers your development and testing, and may even cover light production usage.
You should likely also setup a response in the event of an error.

Alexa: REST API call from intent

I am trying to code a simple skill. I'm trying to call Rest API from each intent.
For example:
TM.prototype.intentHandlers = {
"startIntent": function (intent, session, response) {
console.log("startIntent start");
// HOW TO CALL get http://mysite.site.com/app/start/1234
console.log("startIntent end");
response.ask("bla bla");
},
"endIntent": function (intent, session, response) {
console.log("endIntent start");
//HOW TO CALL post http://mysite.site.com/app/end/1234
console.log("endIntent end");
response.ask("bla bla bla");
},
Can anyone point me how would I called the URLS. I have try in many ways but the it seems that the request never arrived to the server.
Many thanks, Jeff
Repository of Alexa Cookbooks contains a lot of examples. Performing HTTP calls one of them.
The cookbook describes itself as:
AWS Lambda functions running Node.JS can make calls over the Internet
to APIs and services using the https module included in Javascript.
It contains the example how make HTTP calls.
you can use below sample code to call a REST api,
var req = http.get(url, (res) => {
var body = "";
res.on("data", (chunk) => {
body += chunk
});
res.on("end", () => {
var body = JSON.parse(body);
callBack(body)
});
}).on("error", (error) => {
callBack(err);
});
}
Please don't forgot to add the HTTP package like below,
var http = require('http');

Yandex Disk API can't make request with access token node.js

I successfully generated an access token but now I can't use it. Sadly there is no official yandex node library for using the API. There are 2 unofficial npm module that will only work with a server but I want it localhost. As example with code like this, in this case I want to display all files from my disk. Of course I enabled all scopes for my app
request.get('https://cloud-api.yandex.net/v1/disk/resources/files/', {
'auth': {
'bearer': 'xxxxxxxxxxxxxxxxxxx'
}
}, function(err,httpResponse,body){ /* ... */
if(err) {
console.log('err: ' + err)
}
console.log('body: ' + body)
});
Also if I would use https://cloud-api.yandex.net/v1/disk/resources/files?oauth_token=xxxxxxxxxxxxxx&oauth_client_id=xxxxxxxxxxxxxxxxxxx
or https://cloud-api.yandex.net/v1/disk/resources/files?access_token=xxxxxxxxxxxxxx&client_id=xxxxxxxxxxxxxxxxxxx
in my browser I would get
{"message":"?? ???????????.","description":"Unauthorized","error":"UnauthorizedError"}
Somebody has working code or an idea why I´am getting this message?
Now I'm using yandex-disk package. It works enougth for my purposes.
That my steps:
Register app in Yandex Oath Service.
After that I can get info about my app
Realize the access method to get Oath Token by calling this.
npm i yandex-disk
Inserting the code into index.js
const YandexDisk = require('yandex-disk').YandexDisk;
const disk = new YandexDisk('YourOathTokenHere');
console.log('disk', disk);
disk.readdir('/', (err, response) => {
console.log('callback error', err);
console.log('callback response', response);
});
Just include authorization header like that:
axios.get(encodeURI(`https://cloud-api.yandex.net:443/v1/disk/resources?path=${path}`), {
headers: {
'Authorization': `OAuth ${token}`
}
}).then((res) => {
console.log(res);
}).catch((err) => {
console.log(err);
});

Resources