I can access the body of the response but I cannot access the body.success
userInfo:function (req,res) {
var users = [];
db.Users.find({},function (err,result) {
result.forEach(function (user) {
users.push(user);
});
res.json({success:true, userList:users});
});
}
info:function (req,res) {
var options = { method: 'GET',
url: config.auth_url + '/info',
headers:
{
'cache-control': 'no-cache'
},
form:
{}
};
request(options, function (error, response, body) {
if (error)
throw new Error(error);
else if (body.success)
res.json(response.body);
else
res.json({success: false, code: 404});
});
}
This is the response.body
{"success":true,"userList":["5895ea3849616b05d89e27ce","58989c0abe93e41816b91eaf","5899e9bfadf35729818b52b7"]}
Is anyone have idea that I can return appropriate json date because I think that its not a valid json so that it give error.
For the Error :
response.body.success = undefined;
JSON.parse(body) will solve your problem as needed.
Related
I am trying to develop a google cloud function that will make an external https GET request and return the response body to the client.
Flow:
client makes request to mockServer function
function makes GET request to example.com
function returns "results" from response body from example.com to client
exports.mockServer = (req, res) => {
'use strict';
var https = require('https');
var options = {
host: 'example.com',
path: '/path',
headers: {
'accept': 'application/json',
'X-API-Key': 'XXXX'
}
};
if (req.method == 'GET'){
https.get(options, function (res) {
var data = '';
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
if (res.statusCode === 200) {
var res_body = JSON.parse(data);
var results = JSON.stringify(res_body.result)
console.log("results:"+results);
} else {
console.log('Status:', res.statusCode);
}
});
}).on('error', function (err) {
console.log('Error:', err);
});
} else {
console.log("Wrong Method");
}
res.end()
};
I am able to successfully log the results with console.log("results:"+results); but I cannot figure out how to get it returned to the client. I am still new to this and am learning, so thank you so much in advance to any help!
Posting #YouthDev's solution as an answer:
Thanks to #DougStevenson and #Deko in the comments, I switched to an axios library and it works like a charm. Thank you to both for pointing me in the correct direction. Below is the working axios code.
exports.mockServer = (req, res) => {
const axios = require('axios').create({
baseURL: 'https://example.com'
});
return axios.get('/path',{ headers: {'accept': 'application/json','X-API-Key': 'XXXXXX'} })
.then(response => {
console.log(response.data);
return res.status(200).json({
message: response.data
})
})
.catch(err => {
return res.status(500).json({
error: err
})
})
};
I have several API Get request at once in nodejs. Each API have new data every couple minutes.
var express = require('express');
var router = express.Router();
var request = require("request");
let value1, value2, bodyData1, bodyData2;
var options = { method: 'GET',
url: 'https://api.example.com/data1',
qs:
{
valueType: 'MAXIMUM'
},
headers:
{
authorization: 'ABC123456',
accept: 'application/json; charset=utf-8' } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
bodyData1 = JSON.parse(body);
value1 = bodyData1.value;
});
var options = { method: 'GET',
url: 'https://api.example.com/data2',
qs:
{
valueType: 'MAXIMUM'
},
headers:
{
authorization: 'ABC123456',
accept: 'application/json; charset=utf-8' } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
bodyData2 = JSON.parse(body);
value2 = bodyData2.value;
});
router.get('/', function(req, res, next) {
res.render('home', {valueA : value1, valueB: value2});
});
module.exports = router;
I want to know if it is possible to combine them into one function?
Any other things I should concern?
It is possible if you have promises which is currently not the case. You have to wrap your request() call in a Promise. You can do it manually with a custom function requestToPromise.
You can then use Promise.all to call multiple promises in parallel.
function requestToPromise(options) {
return new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (error) return reject(error);
resolve(body);
});
});
}
var optionsRequest1 = {
method: "GET",
url: "https://api.example.com/data1",
qs: {
valueType: "MAXIMUM"
},
headers: {
authorization: "ABC123456",
accept: "application/json; charset=utf-8"
}
};
var optionsRequest2 = {
method: "GET",
url: "https://api.example.com/data2",
qs: {
valueType: "MAXIMUM"
},
headers: {
authorization: "ABC123456",
accept: "application/json; charset=utf-8"
}
};
var requestPromise1 = requestToPromise(optionsRequest1);
var requestPromise2 = requestToPromise(optionsRequest2);
Promise.all([requestPromise1, requestPromise2]).then(results => {
var [resultPromise1, resultPromise2] = results;
}).catch(error => {
//handle error
});
Instead of using the custom function requestToPromise you can also use util.promisify
const util = require('util');
const requestAsync = util.promisify(request);
Promise.all([requestAsync(optionsRequest1), requestAsync(optionsRequest2)]).then(results => {
var [resultPromise1, resultPromise2] = results;
}).catch(error => {
//handle error
});
You can use Redis cache to store data in memory for fast retrieval and fetch from memory very quickly.
Also, after some interval, you can add them to a database through bulk creation. It will decrease your database call.
// Example in sequilize
await db.table_name.bulkcreate([ {0bj1}, {obj2}..,{obj3 } ]);
I would like to know how to send form data with headers to request module.
I have function getToken which makes post request with headers and formdata, and then response data will again make a request to new url and return data.
Currenlty returning
{ type: 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html',
title: 'Unsupported Media Type',
status: 415,
detail: 'Invalid content-type specified' }.
Apologies since not able to provide the apiurl and key
//app.js
var express = require('express');
var router = express.Router();
var helper= require('../help.js');
router.get('/', function (req, res) {
helper.getToken(req.originalUrl).then(token=>{
helper.getData(token).then(data=>{
res.send({api:data})
})
})
})
//helper.js
module.exports.getToken= function (rquery) {
return new Promise(async function (resolve, reject) {
try {
const form_data = {
grant_type: 'auth_token',
auth_token: ''//apikey,
}
var headers = {
"Content-Type": "multipart/form-data",
};
url = ``//apiurl1;
request.post({ url: url, form: form_data, headers: headers }, (e, r, body) => {
if (!e) {
resolve(JSON.parse(body));
}
else {
resolve(e);
}
});
}
catch (err) {
reject(err);
}
})
}
module.exports.getData= function (token) {
return new Promise(async function (resolve, reject) {
try {
const form_data = {
grant_type: 'refresh_token',
refresh_token: token.refresh_token,
}
var headers = {
"Content-Type": "multipart/form-data",
"Authorization":"Bearer "+token.access_token
};
url = ``//apiurl2;
request.post({ url: url, form: form_data, headers: headers }, (e, r, body) => {
if (!e) {
console.log(JSON.parse(body));// returns errors 415
resolve(JSON.parse(body));
}
else {
resolve(e);
}
});
}
catch (err) {
reject(err);
}
})
}
It seems that the API you are posting to does not support multipart/form-data. Can you confirm the Content-Type on the API?
EDIT: Found this in npmjs page of request module: https://www.npmjs.com/package/request#multipartform-data-multipart-form-uploads
The key that you are sending is "form". Try sending "formData" instead
app.get('/profile/:id', function(req, res){
var options = { method: 'GET',
url: 'https://api.favoriot.com/v1/streams?max=1',
headers:
{ 'cache-control': 'no-cache',
'content-type': 'application/json',
'apikey': 'api key' } };
request(options, function (error, response, body) {
res.render('profile', {data:body});
console.log(body)
});
});
when I run code above, I get this data:
{"debugCode":null,"statusCode":200,"numFound":1,"results":[{"user_id":"xxx510","stream_created_at":"2019-03-05T16:13:01.982Z","stream_developer_id":"f8b8fcb9-6f3e-4138-8c6b-d0a7e8xxxxx#xxxx510","device_developer_id":"raspberryPIxx#xxx510","data":{"distance":"12.4","status":"1"}}]}
how can I make it only display status only?
AFAIK there is no issue with the code as such. Are you sure that you got the distance and status in the data field of body or is it the intended output? By try using their API playground by setting your API key on it. I have rewritten the code using ES6 standards by promisifying request module or you can use the request-promise-native.
function requestPromisified(options) {
return new Promise(function(resolve, reject) {
request(options, function(error, res, body) {
if (!error && res.statusCode == 200) {
resolve(body);
} else {
reject(error);
}
});
});
}
app.get("/profile/:id", async (req, res) => {
const options = {
method: "GET",
url: "https://api.favoriot.com/v1/streams?max=1",
headers: {
"cache-control": "no-cache",
"content-type": "application/json",
apikey: "api key"
}
};
try {
const body = await requestPromisified(options);
console.log(body);
res.render("profile", { data: body });
} catch (error) {
res.status(400).send('Unable to find a profile')
}
});
1) There is no middleware in this example... you're just making a call to get some data.
2) status is available in body.results[0].data.status so just use that instead of the entire body object
I'm using request module in express to load a json from a link.
var url = 'https://api.github.com/users/google/repos';
request.get({
url: url,
json: true,
headers: {'User-Agent': 'request'}
}, (err, res, data) => {
if (err) {
console.log('Error:', err);
} else if (res.statusCode !== 200) {
console.log('Status:', res.statusCode);
} else {
// data is already parsed as JSON:
console.log(data.length);
}
});
The output of console.log returns a length of 30.
How can i use the parsed JSON globally (data), outside the function? If i use console.log(data.length) outside it says
Cannot read property 'length' of undefined
Thank you!
You can do it like this
function AnyFunction(res){
//do what you want here
console.log(res.length);
}
const options = {
method: 'GET',
uri: 'https://api.github.com/users/google/repos',
json: true,
headers: {'User-Agent': 'request'}
}
request(options)
.then(function (response) {
// Request was successful, use the response object at will
console.log(response.length);
//you can also pass it in a function and do whatever you want
AnyFunction(response);
})
.catch(function (err) {
// Something bad happened, handle the error
console.log('Error:', err);
})