how to pass query params as array in API calls - node.js

I'm trying to call an API call that accepts array
params = {
uid,
pid,
favorites: [102,110,112,125]
};
const options = {
uri: host + url,
method,
headers,
qs: queryParams,
body: payload,
json: true,
};
try {
const reply = await request(options);
// console.log('server__reply>>>', reply);
return reply;
} catch (err) {
logger.error(`Error:: "${err.message}"`);
// logFailed(service, host + url, reply.status_code, reply.text);
throw new BadRequestException();
}
but whenever i execute the code the params are passed as favorites[]=102,110,112,125
but not as favorites=[102,110,112,125]
is it possible to pass the array, since i can't alter the API since its a third party API

Related

Nodejs wait callback function

I'm new to nodejs.
I want to get my video list using vimeo api.(https://developer.vimeo.com/api/guides/start)
In the following code, I want to return the body or error of the callback function rather than print it.
function get_Vimeo_Data() {
let Vimeo = require('vimeo').Vimeo;
let client = new Vimeo("api_key", "key");
client.request({
method: 'GET',
path: '/me/videos'
}, function (error, body, status_code, headers) {
if (error) {
console.log(error)
}
console.log(body)
});
}
I tried to use promises by referring to various codes, but all failed.
It seems that vimeo api must use callback.
function get_Vimeo_Data() {
let Vimeo = require("vimeo").Vimeo;
let client = new Vimeo("api_key", "key");
return new Promise((resolve, reject) => {
client.request(
{
method: "GET",
path: "/me/videos",
},
function (error, body, status_code, headers) {
if (error) {
//reject(error);
resolve(error);
}
resolve(body);
}
);
});
}
if you do this, then u can just call the function anywhere like this,
await get_Vimeo_Data()
note: I've commented out the reject(error), because u wanted the error to also be returned rather than being thrown as an exception

Problem with validating header/data fields from JQuery AJAX to Backend flask API

I'm trying to pass JWT token and data fields via Jquery and then consume those values in Flask.
So, my client side query looks like this:
function getData() {
var data = {
UserPoolId : 'AWS CognitoUser Pool Id',
ClientId : 'AWS CognitoUser client Id'
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(data);
var cognitoUser = userPool.getCurrentUser();
cognitoUser.getSession(function(err, session) {
if (err) {
alert(err);
return;
}
console.log('session validity: ' + session.isValid());
console.log(cognitoUser.signInUserSession.accessToken.jwtToken);
//
$.ajax({
url: "/api/v1/count",
type: "POST",
headers: { "X-Test-Header": cognitoUser.signInUserSession.accessToken.jwtToken },
// data: JSON.stringify(data),
data: JSON.stringify("{'UserPoolId': 'XXXX','ClientId': 'XXXX'}"),
contentType: 'application/json; charset=utf-8',
error: function(err) {
switch (err.status) {
case "400":
// bad request
break;
case "401":
// unauthorized
break;
case "403":
// forbidden
break;
default:
//Something bad happened
break;
}
},
success: function(data) {
console.log(data);
}
});
//
});
}
Now, in my serverside flask:
I tried to catch the token value using below: which is not working
#app.route("/api/v1/count", methods=["GET", "POST"])
def get_data_count():
if 'X-Test-Header' in request.headers:
headers = request.headers
app.logger.info(headers)
auth = headers.get("X-Test-Header")
app.logger.info('testing info log' + auth)
Also I tried to catch the data fields , using result = request.get_json() also not working.
I tried to inspect in chrome, and I don't see these values being added to the request header.
Can anyone suggest to me if I'm doing it correctly while passing the values from client to server? I also don't see console.log(cognitoUser.signInUserSession.accessToken.jwtToken) in the console log.
if not can anyone suggest to me, how to fix it?

NodeJS HTTP Requests Promises and Storing Results in Variables

I'm building a front-end application that makes HTTP requests to 2 separate API's.
http://greetings_api:3000/getGreeting
data {'language': 'es'}
Response: 'Hola'
http://users_api:3000/getUser
data {'userid': 1}
Response: 'Jose Smith'
I have a single route that makes a request to these API's and then returns those responses:
var http = require('http');
var request = require('request-promise');
var greetingOptions = {
uri: 'http://greetings_api:3000/getGreeting',
hostname: 'greetings_api',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'language': 'es'
}
};
var greeting = {
getGreeting: function() {
return request(greetingOptions);
}
}
function myGreeting() {
return greeting.getGreeting();
};
var userOptions = {
uri: 'http://users_api:3000/getUser',
hostname: 'users_api',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'id': 1
}
};
var user = {
getUser: function() {
return request(userOptions);
}
}
function myUser() {
return user.getUser();
};
function getWelcome(req, res) {
// How do you store this....
myUser().then(function(result) {
console.log('result')
return result;
})
// ...and this...
myGreeting().then(function(result) {
console.log('Greet ' + result);
return result;
});
/// ...and then send them with this?
res.send(greeting + ' ' + user);
}
module.exports = { getWelcome };
So with the current code I get the correct output in the console. The problem is that I need to be able to send the response from the route with the combination of both API responses. What is the simplest way to accomplish this?
You are sending the response before the promises resolving.
with async/await we can write asynchronous code that looks and behaves like synchronous.
async function getWelcome(req, res) {
// we can wrap our operation in a try/catch block to handle
// both asynchronous and synchronous errors
try {
// with the await keyword we can wait for all promises to resolve
// before we continue with our code
/* if one of the promises inside Promise.all rejects we move to the catch block */
const [user, greeting] = await Promise.all([
myUser(),
myGreeting()
]);
// send the response if no errors
res.send(greeting + ' ' + user);
catch(e) {
res.status(404).send();
}
}
You need to make 2 parallel requests and send response after completing both. Here Promise.all function can help you.
Promise.all([myUser(), myGreeting()]).then(function(result) {
// result[0] - user
// result[1] - greeting
res.send(result[0] + ' ' + result[1]);
});

calling external rest api from node without encoding querystring params

I am trying to call an external rest API from node server by using request node module.
let request = require('request');
var options = {
method: 'POST',
url: 'https://somerestURI:3000',
qs: { msg: 'some|data|for|other|server' }
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
If I try to run the above code, query string value is being encoded to
some%7cdata%7cfor%7cother%7cserver
as a result I am not receiving correct response.
But if I fire the same request in POSTMAN. I am receiving the expected output(I think postman is not encoding query string).
So what I want is don't encode the query string value.
Any help would be greatly appreciated.
As answered here, you can disable encoding in qsStringifyOptions
var options = {
method: 'POST',
url: 'https://somerestURI:3000',
qs: { msg: 'some|data|for|other|server' },
qsStringifyOptions: {
encoding: false
}
};
You can use node-rest-client package. It allows connecting to any REST API and get results as javascript Object.
var HttpClient = require('node-rest-client').Client;
var httpClient = new HttpClient();
// GET Call
httpClient.get("http://remote.site/rest/xml/method", function (data, response) {
// parsed response body as js object
console.log(data);
// raw response
console.log(response);
});)
or for POST Call
var args = {
data: { test: "hello" },
headers: { "Content-Type": "application/json" }
};
//POST Call
httpClient.post("http://remote.site/rest/xml/method", args, function (data, response) {
// parsed response body as js object
console.log(data);
// raw response
console.log(response);
});

Podio API addItem call

I'm trying to implement https://developers.podio.com/doc/items/add-new-item-22362 Podio API addItem call in a nodejs module. Here is the code:
var _makeRequest = function(type, url, params, cb) {
var headers = {};
if(_isAuthenticated) {
headers.Authorization = 'OAuth2 ' + _access_token ;
}
console.log(url,params);
_request({method: type, url: url, json: true, form: params, headers: headers},function (error, response, body) {
if(!error && response.statusCode == 200) {
cb.call(this,body);
} else {
console.log('Error occured while launching a request to Podio: ' + error + '; body: ' + JSON.stringify (body));
}
});
}
exports.addItem = function(app_id, field_values, cb) {
_makeRequest('POST', _baseUrl + "/item/app/" + app_id + '/',{fields: {'title': 'fgdsfgdsf'}},function(response) {
cb.call(this,response);
});
It returns the following error:
{"error_propagate":false,"error_parameters":{},"error_detail":null,"error_description":"No matching operation could be found. No body was given.","error":"not_found"}
Only "title" attribute is required in the app - I checked that in Podio GUI. I also tried to remove trailing slash from the url where I post to, then a similar error occurs, but with the URL not found message in the error description.
I'm going to setup a proxy to catch a raw request, but maybe someone just sees the error in the code?
Any help is appreciated.
Nevermind on this, I found a solution. The thing is that addItem call was my first "real"-API method implementation with JSON parameters in the body. The former calls were authentication and getApp which is GET and doesn't have any parameters.
The problem is that Podio supports POST key-value pairs for authentication, but doesn't support this for all the calls, and I was trying to utilize single _makeRequest() method for all the calls, both auth and real-API ones.
Looks like I need to implement one for auth and one for all API calls.
Anyway, if someone needs a working proof of concept for addItem call on node, here it is (assuming you've got an auth token beforehand)
_request({method: 'POST', url: "https://api.podio.com/item/app/" + app_id + '/', headers: headers, body: JSON.stringify({fields: {'title': 'gdfgdsfgds'}})},function(error, response, body) {
console.log(body);
});
You should set content-type to application/json
send the body as stringfied json.
const getHeaders = async () => {
const headers = {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
};
const token = "YOUR APP TOKEN HERE";
headers.Authorization = `Bearer ${token}`;
return headers;
}
const createItem = async (data) => {
const uri = `https://api.podio.com/item/app/${APP_ID}/`;
const payload = {
fields: {
[data.FIELD_ID]: [data.FIELD_VALUE],
},
};
const response = await fetch(uri, {
method: 'POST',
headers: await getHeaders(),
body: JSON.stringify(payload),
});
const newItem = await response.json();
return newItem;
}

Resources