Missing JSON data in External Api passed from Express JS - node.js

I have User Register page which is built with ExpressJS. The data entered here by the user should be passed over to an external Api (Java Rest Api). But I am not getting the JSON data at the receiving end. Also I have to send the response only after creating the User. Below are the code snippets:
Here is my ExpressJS code: (I am using Postman app to post the JSON data here)
router.post('/register', function(req, res, next) {
console.log(req.body); // JSON sent from Postman is showing correctly
var options = {
method: 'POST',
uri: 'http://localhost:3000/userCreation',
body: req.body,
json: true,
headers: { 'Content-Type': 'application/json' }
}
// Here rp is require('request-promise');
rp(options).then(function (res){
console.log("Response from external Api: "+res);
})
.catch(function (err) {
console.log(err);
})
// The response below should be ideally sent after the User Registration is done.
// So it should go into the "then" block. But I am an unable to put it there.
// It says "cannot send header twice"
res.send('Json Data sent to Java/MongoDB & User Created successfully.');
});
This is the code at the receiving end (Java API - but for now, I have another ExpressJS app to test the flow):
router.post('/userCreation', function(req, res, next) {
console.log("User registration in MongoDB");
console.log(req.hostname); // O/p : localhost
console.log(req.body); // O/p : undefined
res.send("User successfully created in MongoDB");
});
Any help/suggestion on this would be really helpful. Thanks in advance.

I got the answer..... "app.use(bodyParser.json())" was required at both the instances of the ExpressJS server. Now it is working fine.

Related

Getting "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client" even though I only have one res.render()

I am using Mongoose and Express/Node.js to build a simple api, but when I try to click on the "Read More" link (which uses Express routing parameters), I get "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client". I understand that this happens when multiple responses are sent for a single post, but I can't for the life of me find where this is happening.
My code is below:
Post.find({}, function(err, foundPosts) {
res.render("home", {homeStartingContent: homeStartingContent, posts: foundPosts});
res.redirect("/");
});
})
app.get("/compose", function(req, res) {
res.render("compose");
})
app.post("/compose", function(req, res) {
const post = new Post({
title: req.body.title,
body: req.body.newPost,
teaser: req.body.newPost.substring(0,99) + "...",
});
// save the post and refresh home page to display most recent post
post.save(function(err) {
if(!err) {
res.redirect("/");
}
});
});
// express routing parameters; uses whatever comes after : to decide what to do
app.get("/posts/:postId", function(req, res) {
const requested = _.lowerCase(req.params.postId);
Posts.findOne({_id: requested}, function(err, post) {
res.render("post", {post: post});
});
});```
I'm pretty sure the issue is in the last app.get("/posts/:postID"...), but I can't figure it out.
I understand that this happens when multiple responses are sent for a single post
It also happens when you send more headers after already having sent a response. And that's what you do by calling first res.render and then res.redirect near the top of your code snippet. Also, this does not make sense, because the redirection will prevent the user from reading what you rendered before.

Unable to post data or send a file using axios and form-data

I am trying to post data from my nodejs app to a an endpoint.
I tested sending some data to that endpoint using Postman and all works fine, I got the posted data and all got printed to the console.
but I am always getting empty post data at my endpoint when sending from my nodejs using axios.
here is my code:
const FormData = require('form-data');
const axios = require('axios');
function send_to_test() {
const endpoint = 'http://localhost:5000/test';
const form = new FormData();
form.append('string_var', 'some string');
form.append('integer_var', 100);
axios.post(endpoint, form, { headers: form.getHeaders() }).then((res) => {
console.log(res.data);
});
};
and here is my endpoint (I am using express js server):
app.post('/test', function(req, res) {
console.log(req.body);
res.json({
status: 'success'
});
});
Unable to get this working, please advise and thanks in advance.
You need to setup a form parser at the your endpoint. You can make use of formidable. code for reference:
const form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
if (err) {
return res.status(400).json({ error: err.message });
}
res.json({
status: 'success'
});
}
I hope it gives you better picture!

microservice with node and needle

I'm trying to make my monolithic application written in node and express to a microservice application in node, needle(to communicate between microservices) and express. My architecture is as follows,
I have a microservice called gateway_service to handle all the requests from frontend UI
I have another microservice called users_service to handle requests related to users, users_service uses passport local strategy to manage sessions and this session id is sent as a cookie by passport
When I try to change my application to microservice I'm doing the following
Whenever I receive a request from my client say, postman in gateway_service I can see the cookie coming through header, and I'm able to pass it to user_service by setting headers option as mentioned in needle.
How to send the cookie that I receive from user_service to the postman back to he can save the cookie(in case of first hit)??
I'm adding a small code snippet, hoping it will help?
Am I doing it in the right way??
when I'm doing as shown below Im getting the error "Cannot set headers after they are sent to the client"
function (req, res, next) {
var options = {
headers: req.headers,
parse_cookies:true
}
needle.post(url + "login", req.body, options, function (error, response, body) {
if (!error) {
res.writeHead(response.statusCode,response.headers);
res.send(body)
console.log(res);
next();
} else {
console.log("error in info from users micro service");
res.send(error);
next();
}
});
},

Problem with redirect using 'fetch' from frontend page

I am using the following JS in a webpage to send information to a Node.js server upon 'clicking' on an image in the webpage, I am having trouble with the 'redirect' once the 'fetch' is executed:
fetch('/members/pages/callup', {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({name: splits[1], presence: available, str: 'Some string: &=&'})
})
.then(function(res) {res.json()})
.then(function(res) {
if(res.response) {
redirect: window.location.replace("/members/pages/" + splits[1]);
} else {
alert("Error in the response");
}
})
.catch(function(err) {
alert("Error in the fetch call..." + err);
})
The fetch seems to properly send the 'body' data to the server. However I am getting the following error: "Error in the fetch call...TypeError: Cannot read property 'response' of undefined"...
The server performs a database call using the information sent by the frontend, and I thought all I needed to do was to send a "200 (OK)" response back...here is the server code:
app.post('/member/pages/callup', jsonParser, function (req, res) {
console.log("I RECEIVED FROM CLIENT THE FOLLOWING:");
console.log(req.body); //works fine, prints output from frontend 'fetch' to console...
db.lookupMember(req.body.name)
.then(function(foundUser) {
console.log('Async success!', foundUser); //works fine, prints database info to console...
if (typeof foundUser != "undefined") {
res.sendStatus(200); //trying this to 'reply' back to 'fetch' in frontend...is this not correct?
} //'foundUser' is NOT'undefined'...
})
.catch(function(error) {
console.log('UNABLE TO RETRIEVE MEMBER INFORMATION FROM THE DATABASE...' + error);
res.redirect('/'); //route to splash page...
});
})
Any suggestions appreciated, this has gone from a minor irritant to a major problem. I thank you in advance.
There are few issues in the code. If fixed, code should work fine.
You forgot to return res.json() from the function at one place. Make it return res.json() and it will work fine (Inside fetch, 1st then). Due to not returning, res is undefined which is giving the error
You are trying to use res.response but res is not send as a proper json from node server. This will fail at res.json(). You should be doing something like res.send({response: true})
After the if loop in server there is syntax error. It needs to be redirect = instead of redirect:. Also redirect is not declared anywhere which. (Note: you might not need redirect variable here, simply window.lo... should also work)
Note: Have updated the original answer after having the discussion with OP

how to fetch data after successful authentification with node, express and react (componentDidMount error)

I'm working on a Node-express-react project where I'm calling the Google Analytics reporting API to display some data on the client-side. Right now I have:
my back-end and my front-end on two separate localhosts
A Google Sign-in Button on the front-end redirecting to the back-end to run the OAuth 2.0 authentication process
I'm calling the ga reporting API once I have the token.
Everything is working well so far. Now I'd like to pass the response from the API call to the client-side (react). I have the following component:
componentDidMount() {
// Pick whatever host/port your server is listening on
fetch('http://localhost:5000/getData')
.then(res => { // <-- The `results` response object from your backend
// fetch handles errors a little unusually
if (!res.ok) {
throw res;
}
// Convert serialized response into json
return res.json()
}).then(data => {
// setState triggers re-render
this.setState({loading: false, data});
}).catch(err => {
// Handle any errors
console.error(err);
this.setState({loading: false, error: true});
});
}
Here is my API call on the server-side
router.get('/getData', function(req, res) {
var token = req.query.token;
request('https://www.googleapis.com/analytics/v3/management/accounts?access_token=' + token, function (error, response, body) {
if(error){
console.log(error);
}else{
console.log(JSON.parse(body))
let views = []
JSON.parse(body).items.forEach(view => {
views.push({
name: view.webPropertyId + ' - ' + view.name + ' (' + view.websiteUrl + ')',
id: view.id
})
})
console.log(views)
res.send(views);
}
});
})
The issue is that the componentDidMount() is being called before I click the Google login button which is running into an error because data from the API are not available (since no authentication has been done yet).
Which logic I should follow to have my data being fetch only once the login has been successful?
Thanks.

Resources