Render API response body content with node.js - javascript

Working with Node.js, I wrote a router implementation as follows:
router.get('/fileshare', oauth2.required, (req, res, next) => {
var apiResponse = null;
// Consume GCP API
const queryObject = {
project: config.get('GCLOUD_PROJECT'),
prefix: 'msf-test-fs'
};
request.get({
url: 'https://www.googleapis.com/storage/v1/b',
qs: queryObject,
auth: {
'bearer': req.user.token
}
}, function(err, res) {
if (err) {
self.callback(err, null);
return;
}
console.log(res.body); // Has content
apiResponse = res.body
});
// Render content
// I WOULD LIKE TO HAVE HERE THE API RESPONSE BODY!!!
console.log(apiResponse); // Is null
res.render('pages/list', { }); // <<-- response body here as param
});
It basically invoke an API endpoint and retrieve an response body.
I would now like to pass the API response body to render a webpage.
However, the apiResponse is null while invoking console.log(apiResponse);.
How could I fix it?

The callback invoked by request is called asynchronously after res.render. You need to move res.render to the callback and stop shadowing res variable.
router.get('/fileshare', oauth2.required, (req, res, next) => {
// Consume GCP API
const queryObject = {
project: config.get('GCLOUD_PROJECT'),
prefix: 'msf-test-fs'
};
request.get({
url: 'https://www.googleapis.com/storage/v1/b',
qs: queryObject,
auth: {
'bearer': req.user.token
}
}, function(err, response) {
if (err) {
self.callback(err, null);
return;
}
console.log(response.body); // Has content
// Render content
console.log(response.body);
res.render('pages/list', JSON.parse(response.body)); // <<-- response body here as param
});
});

Related

Can i use route inside a controller in express js?

So I have something like this in one of my controllers:
module.exports.authToken = (req, res, next) => {
const token = req.cookies.jwt;
//console.log(token);
if (!token) {
return res.sendStatus(403);
}
try {
const data = jwt.verify(token, "secret token");
console.log(data);
req.userId = data.id;
return next();
} catch {
return res.sendStatus(403);
}
};
and it's called by a route:
router.get("/protected", authController.authToken, (req, res) => {
return res.json({ user: { id: req.userId, role: req.userRole } });
});
and I want to get a JSON response of that route in one of my other controllers. I tried some things but none of it worked.
What I would do is abstract the response out to a function for re-use:
// the function will just return the data without writing it to the response
function protectedRoute(req) {
return {user: {id: req.userId, role: req.userRole}};
}
router.get("/protected", authController.authToken, (req, res) => {
// in the actual handler you can return the response
return res.json(protectedRoute(req));
});
// make sure the middleware is still being run
router.get("/other_route", authController.authToken, (req, res) => {
// use the same function to get the response from /protected
const protectedResponse = protectedRoute(req);
// do stuff with it
});

React Callservice script doesn't retrieve the needed information from Node.js script that makes the API call

I'm trying to make a simple webpage using React.js to display information retrieved from an API. I say simple because it should be, but I haven't developed anything for a long time and I seem to have an issue that I can't find the cause off.
I made a node.js file to act as a mediator between my webpage and the API because I was having CORS issues.
Situation:
Whenever I push the button I don't retrieve any information. The call keeps displaying "pending" as status within the network tab(see below image).
But within my Node.js script I can see by logging that I do get the correct response and retrieve all the information I need. So I can state that my node script works as it should.
I think the issue is situated between the exchange from my Node.js script and the CallService.js script. I just can't put my finger on what is wrong.
What am I missing here?
I've provided all the code I have below but left out sensitive information.
Node.js:
const express = require('express');
const request = require('request');
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
app.get('/ListAllModels', (req, res) => {
request(
{
url: '/* api url*/',
headers: {
'Content-Type': 'application/xml',
'X-Tenant-ID': '/*tenant id*/',
'Authorization': 'Basic /*authorization*/'
}
},
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: err.message });
}
console.log(response);
return response;
}
)
});
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));
I made a Callservice.js file in my react app:
import axios from 'axios';
export const getAllEmailModels = () => {
return axios.get("http://localhost:4000/ListAllModels").then(response => {
if (response.statusCode === 200) {
return response;
}
throw new Error("Network response was not ok.");
}).catch(error => {
return error;
});;
};
In my app I made a button that should call on the API and provide the retrieved information in console.
import React, { Component } from 'react'
//import axios from 'axios';
import * as CallService from "../Services/CallService";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {emailModels:[]};
this.emailModelTest = this.emailModelTest.bind(this);
}
emailModelTest() {
console.log("button works");
CallService.getAllEmailModels().then(response => this.setState({
emailModels: response.body,
}), console.log(this.state.emailModels) );
}
render() {
return (
<div>
<button onClick={this.emailModelTest}>test call</button>
</div>
)
}
}
Your problem is in here:
app.get('/ListAllModels', (req, res) => {
request(
{
url: '/* api url*/',
headers: {
'Content-Type': 'application/xml',
'X-Tenant-ID': '/*tenant id*/',
'Authorization': 'Basic /*authorization*/'
}
},
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: err.message });
}
console.log(response);
return response;
}
)
});
It's pending because it there is never a response.
When it goes to your 'ListAllModels' endpoint, it makes a request to another endpoint asynchronously.
When the response comes back it isn't inside the app.get function anymore.
Also, the return response will return the response to the caller of that callback which is inside the request() function. You need to send the response back to your CallService using the res object.
You could wrap it in a promise.
You need to send the response using the res object that is passed in as a parameter. That object represents the response send by the node server. The only way the client can get anything is if you send something through that object using res.send(data). Using return response; doesn't work because it's inside another function. It will be returned to the caller of that function not the parent function app.get()
app.get('/ListAllModels', (req, res) => {
fetch('{{url}}', {
headers: {
'Content-Type': 'application/xml',
'X-Tenant-ID': '{{tenant-ID}}',
'Authorization': 'Basic {{auth}}'
}
}).then(otherRes => {
res.status(200).send(otherRes);
}).error(error => {
res.status(400).end();
});
});

how to use middleware of the auth before route to get token

How can I solve this?
i want get token in router and then router send response.but in this middle ware my code get token after routes called.and how can i access middleware token for verify user
var express = require("express");
var request = require("request");
var router = express.Router();
var supertoken;
tokenmiddleware = function(req, res, next) {
console.log("this is auth middleware");
try {
var options = {
method: "POST",
url: "here is my auth server url",
headers: {
json: true,
Authorization: "", //
"Content-Type": "application/x-www-form-urlencoded"
}
},
form: {
grant_type: "password",
username: "usrename",
password: "password"
};
request(options, function(error, response, body1) {
if (error) {
throw new Error(error);
} else {
let info = JSON.parse(body1);
//it parse the body1 into json so we can use property of body1.
supertoken = info.access_token; //it gives the token of the super admin.
// console.log(supertoken)
// console.log(process.env.ACCESS_TOKEN);
//return supertoken
}
});
console.log("superrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr");
console.log(supertoken);
next();
} catch (error) {
return res.status(401).json({ message: "Auth Failed." });
}
}; //this middleware gave me a token.
router.post("/verifyUser", tokenmiddleware, (req, res) => {
//here i want my middleware token (but it calls after the route)
//here i applied logic of verify user but token is not working.(it say's undefined)
});
Your middleware includes request which is an asynchronous operation. And you call next() outside of request callback. After your middleware called you fire next() before request is finished, just move next inside request callback
tokenmiddleware = function (req, res, next) {
console.log('this is auth middleware');
try {
var options = {
method: 'POST',
url: 'here is my auth server url',
headers: {
json: true,
Authorization: '', //
'Content-Type': 'application/x-www-form-urlencoded',
},
form: {
grant_type: 'password',
username: 'usrename',
password: 'password',
},
};
request(options, function(error, response, body1) {
if (error) {
throw new Error(error);
} else {
let info = JSON.parse(body1);
//it parse the body1 into json so we can use property of body1.
supertoken = info.access_token; //it gives the token of the super admin.
// console.log(supertoken)
console.log('superrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr');
console.log(supertoken);
req.userToken = info.access_token;
next();
}
});
} catch (error) {
return res.status(401).json({ message: 'Auth Failed.' });
}
};
router.post("/verifyUser", tokenmiddleware, (req, res) => {
console.log(req.userToken); // should be your token
});

Route to the view received by Node.js request

Controller code:
bina: function(req, res) {
var request = require('request');
request({
url: 'http://localhost:3000/bina/',
method: 'GET',
}, function(err, res, body) {
if (err) {
console.log(err);
} else {
var data = JSON.parse(res.body);
console.log(data);
res.render(data)
}
})
}
The data that comes with the request does not see any functions like res.view or res.render.
Error output:
res.render(data)
^
TypeError: res.render is not a function
Note:
I can see the data via console.log(data) via web service. I use Sail.js.
Here's what you are doing wrong:
You are using same variable (res) name twice. And at the res.render it taking the one which is in the nearest scope. I have renamed the res => to response and now it should work.
bina: function(req, res) {
var request = require('request');
request({
url: 'http://localhost:3000/bina/',
method: 'GET',
}, function (err, response, body) { // Changed the variable name
if (err) {
console.log(err);
}
else {
var data = JSON.parse(response.body);
console.log(data);
res.render(data)
}
})
}
Hope it solved your issue.

Node.js API returns JSON in terminal but not in browser

Having a strange problem. Been searching for answers but nothing turns up. I'm doing a node api tutorial and it returns JSON from my mongoDB database in my terminal when I perform any GET request but in my browser or postman I get nothing back, only in the terminal do I get any response. When I try a POST in postman it says it can't connect to the backend.
here is my code :
var http = require('http');
var url = require('url');
var database = require('./database');
// Generic find methods (GET)
function findAllResources(resourceName, req, res) {
database.find('OrderBase', resourceName, {}, function (err, resources) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resources));
});
};
var findResourceById = function (resourceName, id, req, res) {
database.find('OrderBase', resourceName, {'_id': id}, function (err, resource) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
});
};
// Product methods
var findAllProducts = function (req, res) {
findAllResources('Products', req, res);
};
var findProductById = function (id, req, res) {
findResourceById('Products', id, req, res);
};
// Generic insert/update methods (POST, PUT)
var insertResource = function (resourceName, resource, req, res) {
database.insert('OrderBase', resourceName, resource, function (err, resource) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
});
};
// Product methods
var insertProduct = function (product, req, res) {
insertResource('OrderBase', 'Product', product, function (err, result) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(result));
});
};
var server = http.createServer(function (req, res) {
// Break down the incoming URL into its components
var parsedURL = url.parse(req.url, true);
// determine a response based on the URL
switch (parsedURL.pathname) {
case '/api/products':
if (req.method === 'GET') {
// Find and return the product with the given id
if (parsedURL.query.id) {
findProductById(id, req, res)
}
// There is no id specified, return all products
else {
findAllProducts(req, res);
}
}
else if (req.method === 'POST') {
//Extract the data stored in the POST body
var body = '';
req.on('data', function (dataChunk) {
body += dataChunk;
});
req.on('end', function () {
// Done pulling data from the POST body.
// Turn it into JSON and proceed to store it in the database.
var postJSON = JSON.parse(body);
insertProduct(postJSON, req, res);
});
}
break;
default:
res.end('You shall not pass!');
}
});
server.listen(8080);
console.log('Up and running, ready for action!');
You have several callbacks with err as first argument but you are not treating any potential error. It means if something is going wrong, you are not catching it and returning an error. I don't know if this has anything to do with it, but as a practice (not even "best", but general practice) instead of doing this
function (err, resource) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
}
do this
function (err, resource) {
if(err){
// do something to warn the client and stop here
}
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
}
Try that, see if you are actually running into errors before trying to output an answer.
https://nodejs.org/api/http.html#http_response_end_data_encoding_callback
The response end method not send data to response socket. Maybe you change it
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
res.writeHead(200, {'Content-Type': 'application/json'});
res.write(JSON.stringify(resource));
res.end();
if you want socket to close to do something, you can into callback to end.
res.end(#logHandle());
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var connect = function (databaseName, callback) {
var url = 'mongodb://localhost:27017/' + databaseName;
MongoClient.connect(url, function (error, database) {
assert.equal(null, error);
console.log("Successfully connected to MongoDB instance!");
callback(database);
})
};
exports.find = function (databaseName, collectioName, query, callback) {
connect(databaseName, function (database) {
var collection = database.collection(collectioName);
collection.find(query).toArray(
function (err, documents) {
assert.equal(err, null);
console.log('MongoDB returned the following documents:');
console.dir(JSON.parse(JSON.stringify(documents)));
//console.dir(documents);
callback(null, documents);
}
)
database.close();
})
};
I think we are going through the same tutorial, this is my solution of 'database.js', works for me.

Categories

Resources