Error: Can't set headers after they are sent Ember/Nodejs - node.js

I am trying to fetch data from an API, if you see the console ,you will find that a huge chunk of JSON that is variable a2 is displayed in the console .
But I wish to do res.json(a2); to display all the json on the webpage as JSON data.
I am getting an error--
Error: Can't set headers after they are sent.
What do I do >
var express = require('express');
var app = express();
const port = 5000;
var gotit = [];
var Request = require("request");
Request.post({
"headers": {
"content-type": "application/json",
"Authorization": "34ca0e9b-ecdd-4736-a432-d87760ae0926"
},
"url": "https://www.lifeguard.insure/v1/quote",
"body": JSON.stringify({
"category": "Auto",
"zipcode": "90293",
"age": 35,
"gender": "Male",
"key": "a2bf34ab-8509-4aa6-aa9e-13ae7917e1b8"
})
}, (error, response, body) => {
if (error) {
return console.dir(error);
}
var a2 = (JSON.parse(body));
console.log(a2)
gotit = a2;
});
console.log("Gotiit")
console.log(gotit);
app.get('/api/customers', (req, res) => {
res.json(gotit);
});
app.listen(port, () => console.log("Server Started"));

It looks like your making that request when your server boots?
maybe it'll work if the request is made inside the route handler?
like,
app.get('/api/customers', (req, res) => {
var gotit = [];
// all that request code, but in here
res.json(gotit);
});

Related

React direct to external NodeJS route and display data from processed body

i have this fetch request which send some body data to http://localhost:8000/report and then redirects to the same route on server to display data after processing :
const handleGo = async () => {
const employee = {
name: name.current.value,
month: month.current.value,
year: year.current.value,
};
await fetch("http://localhost:8000/report", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify(employee),
});
window.location.replace("http://localhost:8000/report");
};
index.json server
const client = require("#jsreport/nodejs-client")("http://localhost:8001");
app.post("/report", (req, res, next) => {
employee.getEmpReport(req, res, next, client);
});
function getEmpReport
const getEmpReport = async (req, res, next, client) => {
const { name, month, year } = req.body; /// processing body data coming from react client
Employee.aggregate([
// doing some MongoDB join with conditions and returning results
]).exec(function (err, employee) {
const dataObject = {
/// setting some data from returned employee
};
client
.render({
template: { name: "/salary/salarySlipTemplate" },
data: dataObject,
options: { reports: { save: true } },
})
.then((response) => response.pipe(res))
.catch(next);
});
};
i want this route to process data and then display data after processing, but when window.location.replace("http://localhost:8000/report"); redirects to the route it says cannot get /report
i think i need a get route but then how can i recieve body data ? i want to be able to recieve the data from client and display it at the same time, how can i do that ?
i should send request from client to jsreport client and send data directly, server should only return the filtered employee:
import jsreport from "#jsreport/browser-client";
jsreport.serverUrl = "http://localhost:8001";
const handleGo = async () => {
const employee = {
name: name.current.value,
month: month.current.value,
year: year.current.value,
};
const response = await fetch("http://localhost:8000/report", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify(employee),
});
const data = await response.json();
const report = await jsreport.render({
template: {
name: "/salary/salarySlipTemplate",
},
data: data,
});
report.openInWindow({ title: "salary slip" });
};

Error in connect econnrefused response from server

I got the error from the server with errorno: ECONNREFUSED
My API is working perfectly on my local machine. When I host the code I got a connection error.
If you hit the URL direct you'll get products http://nodenpm.club:3001/products
Here is the API URL which i'm using for accessing the order with products http://nodenpm.club:3002/orders
but when i access this URL using request i got below error
{
"status": false,
"error": {
"errno": "ECONNREFUSED",
"code": "ECONNREFUSED",
"syscall": "connect",
"address": "172.17.0.3",
"port": 3001
}
}
I am using the Ubuntu server for hosting with docker. I have also tried with proxy request but does not work. below is my code for request.
const express = require("express");
const request = require('request');
const app = express();
app.get("/orders", (req, res) => {
var options = {
url: 'http://nodenpm.club:3001/products',
headers: { 'Content-Type': 'application/json' }
};
request(options, (error, response, body) => {
if (!error) {
res.status(200).json({
status: true,
body: body
});
}
})
});
app.listen(3002, () => {
console.log('order services listening on http://nodenpm.club:3002');
});
my expceted output is below
{
"status": true,
"products": [
{
"_id": "5d5f84afdb78bd0b10e38879",
"name": "mobile",
"price": 10000
}
]
}
i think You have to put the URL into an object for example:
{url:"http://nodenpm.club:3001/products"}
You don't include the method of the request. Try:
request.get(options, (error, response, body) => {
if (!error) {
res.status(200).json({
status: true,
body: body
});
}
})

Using CSRF Token from GET and Uses that in POST | 403 Forbidden | AWS Lambda

I am creating node.js function through aws lambda which makes a GET request to Hybris Market Place and gets a CSRF Token. Then I am using that token to make another POST request to post some data to Hybris Market place but I am getting an error of 403 Forbidden. Same thing works in Postman which I believe due to POSTMAN keeps GET session alive and hence CSRF token is still valid. How May I achieve that in AWS Lambda function. Below is my code. I am using promise to make two requests.
const https = require('https');
exports.handler = async (event, context, callback) => {
const tokenOptions = {
"host": "*******.s4hana.ondemand.com",
"path": "/sap/opu/odata/sap/***********/",
"port": null,
"headers":{
"authorization": "Basic ************=",
"cache-control": "no-cache",
"x-csrf-token": "fetch"
},
"method": "GET"
};
var getToken = (tokenOptions) => {
return new Promise((resolve,reject)=>{
const req = https.request(tokenOptions, (res) => {
var xToken = res.headers["x-csrf-token"];
var sCookies = res.headers["set-cookie"];
var response = [xToken,sCookies]
res.on('data', () => {
console.log('Successfully processed HTTPS response');
resolve(response);
});
res.on('end', () => {
});
});
req.on('error', function(){
reject('Request to get token failed.');
});
req.end();
});
};
var postContent = (response) => {
return new Promise((resolve,reject)=>{
var options = {
"method": "POST",
"host": "*********-***.s4hana.ondemand.com",
"path": "/sap/opu/odata/sap/*********/*******",
"port":null,
"headers":
{ "authorization": "Basic *******==",
"x-csrf-token": response[0],
"accept": "application/json",
"content-type": "application/json",
"cache-control": "no-cache",
},
"cookie":response[1],
"body":
{
/* Data I want to POST */
},
"json": true
};
const req = https.request(options, (res,data) => {
console.log(res.statusCode);
res.on('data', () => {
resolve('Successfully submitted.');
});
res.on('end', () => {
});
});
req.on('error', function(err,res){
reject('Request to get Post failed.');
});
req.end();
});
};
getToken(tokenOptions).then((response) =>{
console.log('Result: ' +response[0]);
return postContent(response);
}).then((successMsg) =>{
callback(null,successMsg);
}).catch((errMsg)=>{
callback();
});
};

Can send post request with curl but cannot from a node server

I can make a post request to a REST api endpoint of a web service with curl successfully but couldnt do so with request module in node.js. Instead, I always get error CONNECTION ETIMEDOUT.What is the problem?
curl command:
curl -i --header "Content-Type: application/json" -XPOST 'http://<endpoint_url>/urls' -d '{
"callback": "http://www.example.com/callback",
"total": 3,
"urls": [ {
"url": "http://www.domain.com/index1.html"
}, {
"url": "http://www.domain.com/index2.html"
}, {
"url": "http://www.domain.com/index3.html"
}
]
}'
code:
function sendRequestToEndPoint() {
const sample = {
"callback": "http://www.example.com/callback",
"total": 3,
"urls": [ {
"url": "http://www.domain.com/index1.html"
}, {
"url": "http://www.domain.com/index2.html"
}, {
"url": "http://www.domain.com/index3.html"
}
]
}
const options = {
method: 'post',
//headers: {
// 'Content-Type': 'application/json',
// 'Accept': 'application/json',
//},
url: 'http://<endpoint_url>/urls',
json: sample
//body: JSON.stringify(sample) // also tried this with headers on
};
console.log(sample);
request(options, (error, response, body) => {
console.log(response)
});
}
Update: Turned out that it was because the api url I used is not correct.
use querystring to stringify your json data,
var querystring = require('querystring');
...
sample = querystring.stringify(sample);
look at this answer How to make an HTTP POST request in node.js
this code works,
you need to Stringify your json object using JSON.stringify , and use the methode write of the object request to send the sample json object
, http = require('http')
, bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
var sample = JSON.stringify({
"callback": "http://www.example.com/callback"
, "total": 3
, "urls": [{
"url": "http://www.domain.com/index1.html"
}, {
"url": "http://www.domain.com/index2.html"
}, {
"url": "http://www.domain.com/index3.html"
}
]
});
var options = {
hostname: 'localhost'
, port: 80
, path: '/test/a'
, method: 'POST'
, headers: {
'Content-Type': 'application/json'
, 'Content-Length': sample.length
}
};
app.get('/', function (req, res) {
var r = http.request(options, (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.setEncoding('utf8');
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
response.on('end', () => {
console.log('No more data in response.');
});
});
r.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
r.write(sample);
r.end();
res.send('ok');
});
a link for more details about http.request nodejs.org http.request(options[, callback])

Error with messenger webhook setup

I am using the same verify token but it's giving me error https://infinite-dusk-17985.herokuapp.com/webhook/ and neither it's responding when I m using it on messenger.
'use strict';
const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const app = express()
app.set('port', (process.env.PORT || 5000))
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))
// parse application/json
app.use(bodyParser.json())
// index
app.get('/', function (req, res) {
res.send('hello world i am a secret bot')
})
// for facebook verification
app.get('/webhook/', function (req, res) {
if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
res.send(req.query['hub.challenge'])
res.send('Sucess, Challenge loop crossed')
}
res.send('Error, wrong token')
})
// to post data
app.post('/webhook/', function (req, res) {
let messaging_events = req.body.entry[0].messaging
for (let i = 0; i < messaging_events.length; i++) {
let event = req.body.entry[0].messaging[i]
let sender = event.sender.id
if (event.message && event.message.text) {
let text = event.message.text
if (text === 'Generic') {
sendGenericMessage(sender)
continue
}
sendTextMessage(sender, "Text received, echo: " + text.substring(0, 200))
}
if (event.postback) {
let text = JSON.stringify(event.postback)
sendTextMessage(sender, "Postback received: "+text.substring(0, 200), token)
continue
}
}
res.sendStatus(200)
})
const token = "EAACKS5K1KvkBAASh07gKvgk9LvjCweLqKxKti1ZBzdzArNFPYNX9ZCx9tu35NNWquJZBuZCdZBLdsZBJAPFhvKgMZBDlazgofkbZAAeE6Hgv3gOh8jRd1W42AAZBIBd7EYNJsADepcpIgSlJEH9kHrup49oT5wZBHZBItnQwwDqr96z4wZDZD"
function sendTextMessage(sender, text) {
let messageData = { text:text }
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token:token},
method: 'POST',
json: {
recipient: {id:sender},
message: messageData,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending messages: ', error)
} else if (response.body.error) {
console.log('Error: ', response.body.error)
}
})
}
function sendGenericMessage(sender) {
let messageData = {
"attachment": {
"type": "template",
"payload": {
"template_type": "generic",
"elements": [{
"title": "First card",
"subtitle": "Element #1 of an hscroll",
"image_url": "http://messengerdemo.parseapp.com/img/rift.png",
"buttons": [{
"type": "web_url",
"url": "https://www.messenger.com",
"title": "web url"
}, {
"type": "postback",
"title": "Postback",
"payload": "Payload for first element in a generic bubble",
}],
}, {
"title": "Second card",
"subtitle": "Element #2 of an hscroll",
"image_url": "http://messengerdemo.parseapp.com/img/gearvr.png",
"buttons": [{
"type": "postback",
"title": "Postback",
"payload": "Payload for second element in a generic bubble",
}],
}]
}
}
}
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token:token},
method: 'POST',
json: {
recipient: {id:sender},
message: messageData,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending messages: ', error)
} else if (response.body.error) {
console.log('Error: ', response.body.error)
}
})
}
// spin spin sugar
app.listen(app.get('port'), function() {
console.log('running on port', app.get('port'))
})
Any help would be highly appreciated.
Since you didn't share the error stack trace, I am not sure about the reason. But, there is an issue with your code.
For the following code snippet,
// for facebook verification
app.get('/webhook/', function (req, res) {
if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
res.send(req.query['hub.challenge'])
res.send('Sucess, Challenge loop crossed')
}
res.send('Error, wrong token')
})
You would definitely be getting Error: Can't set headers after they are sent.
So, update the code with the following.
// for facebook verification
app.get('/webhook/', function (req, res) {
if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
res.send(req.query['hub.challenge'])
console.log('Sucess, Challenge loop crossed')
} else{
res.send('Error, wrong token')
}
})
Here is a working solution:
// my_server.js
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const app = express();
app.set('port', process.env.PORT || 5000);
// parse application/json
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// spin spin sugar
app.listen(app.get('port'), function() {
console.log('running on port', app.get('port'));
});
/* for facebook verification */
app.get('/webhook', function(req, res) {
if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
console.log("Validating webhook");
res.status(200).send(req.query['hub.challenge']);
} else {
console.error("Verification failed. Make sure the validation tokens match.");
res.status(403).end();
}
});
Few things to take note:
When you setup the webhook at developers.facebook.com, make sure the Verification Token you provide their is exactly the same string as found in the above code (i.e. 'my_voice_is_my_password_verify_me')
If you wish to change this token, make sure you update it at both places. This is Very Important
If you deploy this code to Heroku, process.env.PORT will be your port. A hardcoded port number might not work!
You will notice app.use(bodyParser.json()); is used here. This is because Facebook sends JSON data (payload) in the request body
Note that you can't write 2 res.send() statements it will give you error as mentioned by Mukesh. Once the headers are sent it can't be modified
Finally as a best practice, you can try to run it locally using npm run start or node my_server.js and ensure it has no errors like a missing node module & etc although you won't get a success response while running it locally

Resources