How to open port to access API on nodejs - javascript

I am trying to access the Looker API of a self-hosted instance. I am very new to nodejs and not sure how to go about this. THis is the error I am getting:
node:_http_outgoing:742
throw new ERR_INVALID_ARG_TYPE(
^
TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received undefined
at new NodeError (node:internal/errors:372:5)
at write_ (node:_http_outgoing:742:11)
at ServerResponse.write (node:_http_outgoing:707:15)
at Server.<anonymous> (/Users/the_user/Dropbox/products/LookerBot/index.js:63:13)
at Server.emit (node:events:527:28)
at parserOnIncoming (node:_http_server:956:12)
at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17) {
code: 'ERR_INVALID_ARG_TYPE'
}
Node.js v17.9.0
This is what I tried:
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {
'Content-Type': 'text/html'
});
const axios = require('axios');
const qs = require('qs');
const slack_key = 'xoxb-12345';
const looker_client_id = 'GDKGKDRHJGKR123';
const looker_client_secret = 'sdfgfd6789'
const looker_url = `https://mylooker.cloud.looker.com:19999/client_id=${looker_client_id}&client_secret=${looker_client_secret}`;
let dict = {
"url": "https://mylooker.cloud.looker.com",
"apiBaseUrl": looker_url,
'clientId': looker_client_id,
'clientSecret': looker_client_secret
}
console.log(dict)
axios.get(looker_url, {}, {
'client_id': looker_client_id,
'client_secret': looker_client_secret
})
.then(response => console.log(response))
.catch(error => console.log(error))
let slack_API = 'https://slack.com/api';
let the_text = new URL('https://mylooker.cloud.looker.com/x/123456789');
const greet = () => {
let messageArgs = {
token: slack_key,
channel: '#testing',
text: the_text.toString()
};
post(messageArgs);
};
const post = async (args) => {
const result = await axios.post(`${slack_API}/chat.postMessage`, qs.stringify(args));
try {
console.log(result.data);
} catch (e) {
console.log(e);
}
};
greet();
response.write(request.looker_url);
response.end();
}).listen(19999);
I am trying to create lookerbot and need to build a simple Node.js application. The application needs to be able to reach, both, my Looker instance's API and Slack's API. I am trying to open up port 19999 in order to accesss the Looker API.
What am I doing wrong?

Related

Get unread gmail mails with imap

Hello I'm trying to iplement some basics Google Api features and I get some issues when I try to get the unread messages in the gmail mailbox. Here is my code:
require('dotenv').config();
const nodemailer = require('nodemailer')
const { google } = require('googleapis')
const Imap = require('imap');
const CLIENT_ID = process.env.GOOGLE_CLIENT_ID
const CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET
const REDIRECT_URI = process.env.GOOGLE_REDIRECT_URL
const REFRESH_TOKEN = process.env.GOOGLE_REFRESH_TOKEN
const oauht2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI)
oauht2Client.setCredentials({refresh_token : REFRESH_TOKEN})
function newMessages(/*onNewEmailCallback*/) {
const imap = new Imap({
user: "mymail#gmail.com",
xoauth2: oauht2Client.getAccessToken(),
host: 'imap.gmail.com',
port: 993,
tls: true,
tlsOptions: {
rejectUnauthorized: false
}
});
function showError(error) {
console.error('Error:', error);
}
function showMessage(msg) {
onNewEmailCallback(msg.subject);
console.log(msg.subject);
}
imap.connect();
imap.once('ready', () => {
imap.openBox('INBOX', true, (err, box) => {
if (err) showError(err);
imap.on('mail', (numNewMsgs) => {
imap.search(['UNSEEN'], (err, results) => {
if (err) showError(err);
results.forEach((result) => {
const f = imap.fetch(result, { bodies: '' });
f.on('message', (msg) => {
msg.on('body', (stream, info) => {
let buffer = '';
stream.on('data', (chunk) => {
buffer += chunk.toString('utf8');
});
stream.on('end', () => {
showMessage(Imap.parseHeader(buffer));
});
});
});
});
});
});
});
});
imap.once('error', showError);
imap.once('end', () => {
console.log('Connection terminée');
});
return imap;
}
When I call it in the index.js I get the error
/home/.../node_modules/imap/lib/Connection.js:1804
return str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"');
^
TypeError: str.replace is not a function
at escape
I'm probably passing a bad argument during the imap connection but I don't really know which one and I don't find anything online. Help PLEASE
By the way I had a certificate issue that's why I add the tlsOptions property.
Here the full traceback of the error:
/home/lerou/B-DEV-500-COT-5-2-area-segnon.gnonlonfoun/Back-End/node_modules/imap/lib/Connection.js:1804
return str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"');
^
TypeError: str.replace is not a function
at escape (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Connection.js:1804:14)
at Connection.<anonymous> (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Connection.js:1672:24)
at Connection._resTagged (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Connection.js:1535:22)
at Parser.<anonymous> (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Connection.js:194:10)
at Parser.emit (node:events:512:28)
at Parser._resTagged (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Parser.js:175:10)
at Parser._parse (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Parser.js:139:16)
at Parser._tryread (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Parser.js:82:15)
at Parser._cbReadable (/home/lerou/B-DEV-500-COT-5-2-area-/Back-End/node_modules/imap/lib/Parser.js:53:12)
at TLSSocket.emit (node:events:512:28)

TypeError when instantiaing SpotifyWebApi object

im trying to write a bot to do some playlist handling in spotify. I'm using the spotify-web-api-node package : https://github.com/thelinmichael/spotify-web-api-node
I installed the package and whenever I try to create an object with the following code:
const SpotifyWebApi = require('spotify-web-api-node');
const spotifyApp = SpotifyWebApi();
I keep getting this error:
this._credentials = credentials || {};
^
TypeError: Cannot set properties of undefined (setting '_credentials')
this is the contructor signature in the src file:
constructor(credentials?: Credentials);
Any thoughts ?
You need an access-token for access API call.
In the documentation,
If you've got an access token and want to use it for all calls, simply use the API object's set method. Handling credentials is described in detail in the Authorization section.
spotifyApi.setAccessToken('<your_access_token>');
Demo code: get access token then get Elvis' albums
const SpotifyWebApi = require('spotify-web-api-node');
const axios = require('axios')
const getToken = async () => {
try {
const response = await axios.post(
url = 'https://accounts.spotify.com/api/token',
data = '',
config = {
params: {
'grant_type': 'client_credentials'
},
auth: {
username: '<your client id>',
password: '<your client secret>'
}
}
);
return Promise.resolve(response.data.access_token);
} catch (error) {
return Promise.reject(error);
}
}
getToken()
.then(token => {
const spotifyApi = new SpotifyWebApi();
spotifyApi.setAccessToken(token);
// Passing a callback - get Elvis' albums in range [0...1]
spotifyApi.getArtistAlbums('43ZHCT0cAZBISjO8DG9PnE', { limit: 2, offset: 0 }).then(
(data) => {
console.log('Artist albums', data.body);
},
(err) => {
console.error(err);
}
);
})
.catch(error => {
console.log(error.message);
});
Result

How do I add parameters to https get request?

I am working on a little project to learn how to work with APIs by making GET requests to the Twitter API v2 via a node server.
For the get requests I am using Node's built in https package.
I made a basic GET request that returns a list of the last 10 tweets from a user.
I think in order to increase the amount of tweets I can get I have to make a separate parameter object, which I then implement in the get request.
Right now my function looks like this:
function getTweets() {
const options = {
host: "api.twitter.com",
path: `/2/users/${userId}/tweets`,
headers: {
authorization:
`Bearer ${bearerToken}`,
},
};
https
.get(options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
let jsonObject = JSON.parse(data);
tweetObjects = jsonObject.data;
tweetObjects.map((item) => {
let tweetWords = "";
tweetWords += item.text;
userTweets.push(tweetWords);
});
const result = userTweets.flatMap((str) => str.split(" "));
console.log(result);
});
})
.on("error", (error) => {
console.log(error);
});
}
Right now I only have the options object with host, path, and headers in the request.
This is what I am trying to do:
function getTweets() {
const options = {
host: "api.twitter.com",
path: `/2/users/${userId}/tweets`,
headers: {
authorization:
`Bearer ${bearerToken}`,
},
};
let params = {
max_results: 100,
};
https
.get(params, options, (response) => {
let data = "";
response.on("data", (chunk) => {
data += chunk;
});
response.on("end", () => {
let jsonObject = JSON.parse(data);
tweetObjects = jsonObject.data;
tweetObjects.map((item) => {
let tweetWords = "";
tweetWords += item.text;
userTweets.push(tweetWords);
});
const result = userTweets.flatMap((str) => str.split(" "));
console.log(result);
});
})
.on("error", (error) => {
console.log(error);
});
}
But I get
throw new ERR_INVALID_ARG_TYPE('listener', 'Function', listener);
^
TypeError [ERR_INVALID_ARG_TYPE]: The "listener" argument must be of type function. Received an instance of Object
at checkListener (events.js:131:11)
at ClientRequest.once (events.js:496:3)
at new ClientRequest (_http_client.js:215:10)
at request (https.js:326:10)
at Object.get (https.js:330:15)
at IncomingMessage.emit (events.js:388:22)
at endReadableNT (internal/streams/readable.js:1336:12)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
code: 'ERR_INVALID_ARG_TYPE'
You can either only pass the URL or an object containing options as stated in the docs:
https://nodejs.org/api/https.html#https_https_get_url_options_callback
So you might want to try something like this:
function getTweets() {
let params = {
max_results: 100,
};
const options = {
host: "api.twitter.com",
path: `/2/users/${userId}/tweets?max_results=${params.max_results}`,
headers: {
authorization:
`Bearer ${bearerToken}`,
},
};
https
.get(options, (response) => {
let data = "";
...
}
I am not sure to understand what you are calling parameters that you want to give to the get request.
Anyway a get request does not take some body or parameter. If you want to add some data to the core of your request you have to use the post method and not the get one.
Can you show us the import of https library just to check the functions that it propose?
Best Regards,
Hugo Delatte

Azure function don't accept to create file on remote

I would download file on local the create a stream then send to an API.
In localhost files get created via blobClient.downloadToFile(defaultFile);
But When I deploy function it can not find file to stream, so I think that the download does not happen or in bad location.
I get this error
[Error: ENOENT: no such file or directory, open 'D:\home\site\wwwroot\importPbix\exampleName.pbix'
Here's my code
const blobServiceClient = BlobServiceClient.fromConnectionString(
process.env.CONNEXION_STRING
);
const containerClient = blobServiceClient.getContainerClient(
params.containerName
);
const blobClient = containerClient.getBlobClient(process.env.FILE_LOCATION); // get file from storage
let blobData;
var defaultFile = path.join(params.baseDir, `${params.reportName}.pbix`); // use path module
let stream;
try {
blobData = await blobClient.downloadToFile(defaultFile);
console.log(blobData);
stream = fs.createReadStream(defaultFile);
} catch (error) {
params.context.log(error);
console.log(error);
}
var options = {
method: "POST",
url: `https://api.powerbi.com/v1.0/myorg/groups/${params.groupId}/imports?datasetDisplayName=${params.reportName}`,
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${params.accessToken} `,
},
formData: {
"": {
value: stream,
options: {
filename: `${params.reportName}.pbix`,
contentType: null,
},
},
},
};
//check if file keep in mem
return new Promise(function (resolve, reject) {
request(options, function (error, response) {
if (error) {
params.context.log(error);
reject(error);
} else {
params.context.log(response);
resolve(response.body);
}
fs.unlinkSync(defaultFile);
});
});
I found this post having same issue , that's why I user path module and passed __dirname to function params.baseDir.
If you want to download a file from Azure blob and read it as a stream, just try the code below, in this demo, I try to download a .txt file to a temp folder(you should create it first on Azure function)and print its content from the stream for a quick test:
module.exports = async function (context, req) {
const { BlockBlobClient } = require("#azure/storage-blob")
const fs = require('fs')
const connStr = '<connection string>'
const container = 'files'
const blobName = 'test.txt'
const tempPath = 'd:/home/temp/'
const tempFilePath = tempPath + blobName
const blobClient = new BlockBlobClient(connStr,container,blobName);
await blobClient.downloadToFile(tempFilePath).then(async function(){
context.log("download successfully")
let stream = fs.createReadStream(tempFilePath)
//Print text content,just check if stream has been readed successfully
context.log("text file content:")
context.log(await streamToString(stream))
//You can call your API here...
})
function streamToString (stream) {
const chunks = [];
return new Promise((resolve, reject) => {
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
stream.on('error', (err) => reject(err));
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
})
}
context.res = {
body: 'done'
}
}
Result
File has been downloaded:
read as stream successfully:

Using Node.js to connect to a REST API

Is it sensible to use Node.js to write a stand alone app that will connect two REST API's?
One end will be a POS - Point of sale - system
The other will be a hosted eCommerce platform
There will be a minimal interface for configuration of the service. nothing more.
Yes, Node.js is perfectly suited to making calls to external APIs. Just like everything in Node, however, the functions for making these calls are based around events, which means doing things like buffering response data as opposed to receiving a single completed response.
For example:
// get walking directions from central park to the empire state building
var http = require("http");
url = "http://maps.googleapis.com/maps/api/directions/json?origin=Central Park&destination=Empire State Building&sensor=false&mode=walking";
// get is a simple wrapper for request()
// which sets the http method to GET
var request = http.get(url, function (response) {
// data is streamed in chunks from the server
// so we have to handle the "data" event
var buffer = "",
data,
route;
response.on("data", function (chunk) {
buffer += chunk;
});
response.on("end", function (err) {
// finished transferring data
// dump the raw data
console.log(buffer);
console.log("\n");
data = JSON.parse(buffer);
route = data.routes[0];
// extract the distance and time
console.log("Walking Distance: " + route.legs[0].distance.text);
console.log("Time: " + route.legs[0].duration.text);
});
});
It may make sense to find a simple wrapper library (or write your own) if you are going to be making a lot of these calls.
Sure. The node.js API contains methods to make HTTP requests:
http.request
http.get
I assume the app you're writing is a web app. You might want to use a framework like Express to remove some of the grunt work (see also this question on node.js web frameworks).
/*Below logics covered in below sample GET API
-DB connection created in class
-common function to execute the query
-logging through bunyan library*/
const { APIResponse} = require('./../commonFun/utils');
const createlog = require('./../lib/createlog');
var obj = new DB();
//Test API
routes.get('/testapi', (req, res) => {
res.status(201).json({ message: 'API microservices test' });
});
dbObj = new DB();
routes.get('/getStore', (req, res) => {
try {
//create DB instance
const store_id = req.body.storeID;
const promiseReturnwithResult = selectQueryData('tablename', whereField, dbObj.conn);
(promiseReturnwithResult).then((result) => {
APIResponse(200, 'Data fetched successfully', result).then((result) => {
res.send(result);
});
}).catch((err) => { console.log(err); throw err; })
} catch (err) {
console.log('Exception caught in getuser API', err);
const e = new Error();
if (err.errors && err.errors.length > 0) {
e.Error = 'Exception caught in getuser API';
e.message = err.errors[0].message;
e.code = 500;
res.status(404).send(APIResponse(e.code, e.message, e.Error));
createlog.writeErrorInLog(err);
}
}
});
//create connection
"use strict"
const mysql = require("mysql");
class DB {
constructor() {
this.conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'pass',
database: 'db_name'
});
}
connect() {
this.conn.connect(function (err) {
if (err) {
console.error("error connecting: " + err.stack);
return;
}
console.log("connected to DBB");
});
}
//End class
}
module.exports = DB
//queryTransaction.js File
selectQueryData= (table,where,db_conn)=>{
return new Promise(function(resolve,reject){
try{
db_conn.query(`SELECT * FROM ${table} WHERE id = ${where}`,function(err,result){
if(err){
reject(err);
}else{
resolve(result);
}
});
}catch(err){
console.log(err);
}
});
}
module.exports= {selectQueryData};
//utils.js file
APIResponse = async (status, msg, data = '',error=null) => {
try {
if (status) {
return { statusCode: status, message: msg, PayLoad: data,error:error }
}
} catch (err) {
console.log('Exception caught in getuser API', err);
}
}
module.exports={
logsSetting: {
name: "USER-API",
streams: [
{
level: 'error',
path: '' // log ERROR and above to a file
}
],
},APIResponse
}
//createlogs.js File
var bunyan = require('bunyan');
const dateFormat = require('dateformat');
const {logsSetting} = require('./../commonFun/utils');
module.exports.writeErrorInLog = (customError) => {
let logConfig = {...logsSetting};
console.log('reached in writeErrorInLog',customError)
const currentDate = dateFormat(new Date(), 'yyyy-mm-dd');
const path = logConfig.streams[0].path = `${__dirname}/../log/${currentDate}error.log`;
const log = bunyan.createLogger(logConfig);
log.error(customError);
}
A more easy and useful tool is just using an API like Unirest; URest is a package in NPM that is just too easy to use jus like
app.get('/any-route', function(req, res){
unirest.get("https://rest.url.to.consume/param1/paramN")
.header("Any-Key", "XXXXXXXXXXXXXXXXXX")
.header("Accept", "text/plain")
.end(function (result) {
res.render('name-of-the-page-according-to-your-engine', {
layout: 'some-layout-if-you-want',
markup: result.body.any-property,
});
});

Categories

Resources