How to fix 'headers already sent' error in node - node.js

So I'm trying to create a node app that calls an ldap serve and to authenticate users. In the code below, the app successfully connects to the server and processes the request. But when I try to send a response back, I get this error:
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I'm not really sure why this is occurring. I'm pretty new to node, express, and ldap
// ldapjs required for ldap connection
const ldap = require('ldapjs');
//express required for exposing endpoints
const express = require('express');
const app = express();
const assert = require('assert');
var client = ldap.createClient({
url: 'ldap://someserve.com'
});
//Search filter for users in the directory
var opts = {
filter: '(&(objectCategory=person)(objectClass=user))',
scope: 'sub',
};
//General Ldap serch user
var UserName = '123.test.com';
var Pass = '123longpass'
//Base URL
app.get('/', (req,res) => {
res.send('hello from node')
});
//Get all ldap users
app.get('/api/ldapUsers', (req, res) =>
{
client.bind(UserName, Pass, function (err)
{
client.search('DC=sdf,DC=sdfa,DC=gdfgd', opts, function (err, search)
{
search.on('searchEntry', function (entry)
{
res.setHeader('Content-Type', 'application/json');
var users = entry.object;
console.log(users);
res.json(users);
res.end();
});
});
});
// client.unbind( err => {
// assert.ifError(err);
// });
});
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}...`));

searchEntry event is called once for each found item which means you are calling res.json multiple times.
Try this:
app.get('/api/ldapUsers', (req, res) =>
{
client.bind(UserName, Pass, function (err)
{
client.search('DC=sdf,DC=sdfa,DC=gdfgd', opts, function (err, search)
{
var users = [];
search.on('searchEntry', function (entry) {
users.push(entry.object);
});
search.on('end', function (entry) {
res.setHeader('Content-Type', 'application/json');
console.log(users);
res.json(users);
res.end();
});
});
});
});

Related

ERR_HTTP_HEADERS_SENT node js socket connection

I am building an API that uses socket connection to interact with a server backend built in C#. This is what I have so far
const request = require('request');
const express = require('express');
const app = express();
var server = require('http').createServer(app);
var cors = require("cors");
app.use(cors());
const net = require('net');
const client = new net.Socket();
const stringToJson=require('./stringToJson')
const port = process.env.PORT;
const host = process.env.HOST;
client.keepAlive=true
client.on('close', function() {
console.log('Connection closed');
});
app.get('/getScores',function (req,res) {
let dataSend=''
client.on('data', function (data) {
console.log('Server Says : ' + data);
if(data!='ANALYSIS-ERROR'){
dataSend=stringToJson.stringToJson(data)
}
else{
dataSend=stringToJson.stringToJson('0:0.0:0.0:0.0:0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0')
}
client.destroy()
return res.send(dataSend)
});
client.connect(port, host, function () {
client.write(`GENERAL-ANALYSIS|${req.query.id}|${req.query.website}|`)
return
});
return
})
app.get('/getPlace',function (req,res) {
console.log(req.query)
request(
{ url: `https://maps.googleapis.com/maps/api/place/textsearch/json?query=${req.query.name}+in+${req.query.city}&key=${process.env.API_KEY}` },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: error.message });
}
return res.json(JSON.parse(body));
}
)
})
//TODO ADD 404 500 PAGES
app.use((req, res, next) => {
res.status(404).send("Sorry can't find that!");
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
server.listen(9000, () => {
console.log(`App running at http://localhost:9000`);
});
Basically it creates a connection with the server and listens for some data to be sent back. Then processes the string and sends it to the React frontend. The api calls are made by the frontend using axios
It works but if you refresh the page it throws this error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
How do I fix this?
Try setting the headers as found in the documentation request.setHeader(name, value)
request.setHeader('Content-Type', 'application/json');

Cors proxy issues within server.js file(react, express,sql)

I have made a basic fullstack website using mssql and express. Originally the get routes worked but after implementing the post route they have stopped.
I believe I am receiving a cors error which is.
Proxy error: Could not proxy request /admin-view-users from localhost:3000 to http://localhost:5000/.
[1] See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
my server.js
const express = require("express");
const sql = require("mssql");
var cors = require("cors");
const path = require("path");
var bodyParser = require("body-parser");
const port = process.env.PORT || 5000;
const app = express();
app.use(cors());
app.use(express.json());
const config = {
user: "sas",
password: "Mypassword456",
server: "DEVSQL_2014", // You can use 'localhost\\instance' to connect to named instance
database: "TestDBWebsite"
};
//AdminView users just pulls the users from the database
app.get("/admin-view-users", cors(), function(req, res) {
// connect to your database
sql.connect(config, function(err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query("select * from Users2 ", function(err, recordset) {
if (err) console.log(err);
// send records as a response
res.json(recordset);
res.end();
});
});
});
app.get("/admin-view-users", function(req, res) {
// connect to your database
sql.connect(config, function(err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query("select * from Users2 ", function(err, recordset) {
if (err) console.log(err);
// send records as a response
res.json(recordset);
res.end();
});
});
});
app.get("/user-questions", function(req, res) {
// connect to your database
sql.connect(config, function(err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query("select * from Questions ", function(err, recordset) {
if (err) console.log(err);
// send records as a response
res.json(recordset);
});
});
});
//
var jsonParser = bodyParser.json();
app.use(express.bodyParser());
app.post("/admin-Add-Users", jsonParser, function(request, response) {
var email = req.body.email;
var password = req.body.password;
var request = new sql.Request();
// query to the database and get the records
console.log(email, password); // your JSON
// echo the result back
console.log(request.body);
request.query(
"insert into Login (email, password) values ('" +
email +
"','" +
password +
"')",
function(err, recordset) {
if (err) console.log(err);
}
);
response.send({ message: "Success" });
});
app.listen(port, () => `Server running on port ${port}`);
I have included "app.use(cors());" which I assumed woudl resolve this but it has not.
Please advice if you can .
The first thing that comes up to my mind is the double use of CORS.
You are putting it uptop in the middleware stack and then calling it again in here:
app.get("/admin-view-users", cors(), function(req, res) {
Please try using this only once:
https://www.npmjs.com/package/cors

Node js: res.json not displaying anything

I would like to fetch all the data (users) from a localdb using mongodb and node.js. but res.json(usersArray) is not displaying anything. I also tried to use .render but it would give me another error.
var express = require('express');
var mongojs = require('mongojs');
var db = mongojs('mongodb://localhost/mydb', ['users']);
var app = express();
const port = 5000;
app.use(express.static(__dirname + "/public"));
app.get('/', function(req, res){
console.log("I received a GET request")
/*
db.users.find(function(err, docs){
console.log("Getting data from db");
console.log(docs);
//res.json(docs);
});
*/
let usersArray = db.users.find().toArray(function(err, docs){
console.log("Getting data from db");
console.log(docs);
//res.json(docs);
});;
res.json(usersArray);
//usersString = JSON.stringify(usersArray);
//res.render(usersString);
//res.json(usersString);
console.log("Returned data");
});
app.listen(port,'0.0.0.0');
console.log('Server running on port '+port);
use async await to block promise-based asynchronous functions
app.get('/', async function(req, res){
console.log("I received a GET request")
let usersArray = await new Promise((resolve, reject) => {
db.users.find().toArray((err, docs) => {
if (err)
reject(err)
resolve(docs)
})
});
res.json(usersArray);
//usersString = JSON.stringify(usersArray);
//res.render(usersString);
//res.json(usersString);
console.log("Returned data");
});

Express.js nested routes without parameters

I have a Express server resolving GET /companies/:id/populate/. Now, I would like to setup GET /companies/populate/ (without the :id). However, I can't make this route to work. If I try, for example, GET /companies/all/populate/, it works, so it seems the pattern for an Express route is path/:key/path/:key.
Is this true? Thanks!
Edit: Adding code.
server.js
'use strict';
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var cors = require('cors');
var mongoUri = 'mongodb://localhost:27017';
mongoose.connect(mongoUri);
var db = mongoose.connection;
db.on('error', function() {
throw new Error('Unable to connect to database at' + mongoUri);
});
// runs Express
var app = express();
// uses Cors
app.use(cors());
// uses bodyParser
app.use(bodyParser.json());
// requires Mongo models
require('./models');
// includes routes.js, passing the object 'app'
require('./routes')(app);
// listens for connections on port 3000
app.listen(3000, function() {
console.log("Express started on Port 3000");
});
routes.js
module.exports = function(app) {
// thumbs up if everything is working
app.get('/', function(req, res, next) {
res.send('👍');
console.log('Server Running');
res.end();
});
// companies
var companies = require('./controllers/companies');
app.get('/companies', companies.findAll);
app.get('/companies/:id', companies.findById);
app.get('/companies/:id/populate', companies.populate);
app.get('/companies/populate', companies.populateAll);
app.post('/companies', companies.add);
app.patch('/companies/:id', companies.patch);
app.delete('/companies/:id', companies.delete);
};
/controllers/companies.js
var mongoose = require('mongoose');
Company = mongoose.model('Company');
// GET /companies
// status: works, needs error handling
exports.findAll = function(req, res) {
Company.find({}, function(err, results) {
return res.send(results);
});
};
// GET /companies/:id
// status: works, needs to check error handling
exports.findById = function(req, res) {
var id = req.params.id;
Company.findById(id, function(err, results) {
if (results) res.send(results);
else res.send(204);
});
};
// POST /companies
// status: works, needs error handling
exports.add = function(req, res) {
Company.create(req.body, function(err, results) {
if (err) {
return console.log(err)
} else {
console.log('company created');
}
return res.send(results);
});
};
// PATCH /companies/:id
// status: works, needs error handling
exports.patch = function(req, res) {
var id = req.params.id;
var data = req.body;
Company.update( { '_id' : id }, data, function(err, numAffected) {
if (err) return console.log(err);
return res.send(200);
});
};
// DELETE /companies/:id
// status: works, needs error handling, make sure that we are sending a 204 error on delete
exports.delete = function(req, res) {
var id = req.params.id;
Company.remove({ '_id': id }, function(results) {
console.log('deleted ' + id); // tester
return res.send(results);
});
};
// GET /companies/:id/populate
exports.populate = function(req, res) {
var id = req.params.id;
Company
.findOne({ _id: id })
.populate('contacts country')
.exec(function (err, results) {
if (err) return handleError(err);
else res.send(results);
});
};
// GET /companies/populate
exports.populateAll = function(req, res) {
Company
.find({})
.populate('contacts country')
.exec(function (err, results) {
if (err) return handleError(err);
else res.send(results);
});
};

Express: Can't set headers after they are sent

Following is my server file. I am making 2 calls, one post and one get. It works fine at times. But gives an error of : Can't set headers after they are sent. Does this have anything to do with my client side code?
server.js
var express = require('express')
var mongoose = require('mongoose')
var path = require('path')
var bodyParser = require("body-parser")
var cors = require("cors")
var app = express()
var port = process.env.PORT || 3000
var Url = require("./data/url-schema");
//Express request pipeline
app.use(express.static(path.join(__dirname,"../client")))
app.use(bodyParser.json())
app.use(cors());
/*
Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response.
*/
app.get('*', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/:code', function(req, res) {
console.log("reg", req.params.code)
Url.findOne({code:req.params.code}, function(err, data){
console.log("data", data)
if(data)
res.redirect(302, data.longUrl)
else
res.end()
})
})
app.post('/addUrl', function (req, res, next) {
console.log("on create");
Url.findOne({longUrl:req.body.longUrl}, function(err, data) {
if (err)
res.send(err);
else if(data) {
console.log("already exists",data)
res.send("http://localhost:3000/"+data.code);
} else {
var url = new Url({
code : Utility.randomString(6,"abcdefghijklm"),
longUrl : req.body.longUrl
});
console.log("in last else data created",url)
url.save(function (err, data) {
console.log(data)
if (err)
res.send(err);
else
res.send("http://localhost:3000/"+data.code);
});
}
});
})
app.listen(port, function () {
console.log('Example app listening on port 3000!')
});
// Connect to our mongo database
mongoose.connect('mongodb://localhost/shortUrl');
I get the Following error
error
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:718:10)
at ServerResponse.location (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:835:8)
at ServerResponse.redirect (/opt/lampp/htdocs/url-shortener/node_modules/express/lib/response.js:874:8)
at Query.<anonymous> (/opt/lampp/htdocs/url-shortener/server/server.js:30:8)
at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:177:19
at /opt/lampp/htdocs/url-shortener/node_modules/mongoose/node_modules/kareem/index.js:109:16
at process._tickCallback (node.js:355:11)
From the execution order, in * route handler, the body is being assigned to the response and then in /:code, the response code 302 is being added, where Location header is also added, hence the error. Any header must be added before the body to the response.
To solve this problem, simply change the order of the two GET statements.
Finally found the solution:
var express = require('express')
var mongoose = require('mongoose')
var path = require('path')
var bodyParser = require("body-parser")
var app = express()
var port = process.env.PORT || 3000
var Url = require("./data/url-schema")
var Utility = require("./utility")
//Express request pipeline
app.use(express.static(path.join(__dirname,"../client")))
app.use(bodyParser.json())
/*
Your server must be ready to handle real URLs. When the app first loads at / it will probably work, but as the user navigates around and then hits refresh at /dashboard your web server will get a request to /dashboard. You will need it to handle that URL and include your JavaScript application in the response.
*/
app.get('/dashboard', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/about', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
app.get('/:code', function(req, res) {
Url.findOne({code:req.params.code}, function(err, data){
if(data){
res.redirect(302, data.longUrl)
}
})
})
app.post('/addUrl', function (req, res, next) {
Url.findOne({longUrl:req.body.longUrl}, function(err, data) {
if (err){
res.send(err)
}
else if(data) {
res.send("http://localhost:3000/"+data.code);
} else {
var newCode = getCode()
checkCode(newCode)
.then(function(data){
var url = new Url({
code : data,
longUrl : req.body.longUrl
});
url.save(function (err, data) {
if (err)
res.send(err);
else
res.send("http://localhost:3000/"+data.code);
});
})
}
});
})
app.listen(port, function () {
console.log('Example app listening on port 3000!')
});
// Connect to our mongo database
mongoose.connect('mongodb://localhost/shortUrl');
//Generate a random code
function getCode() {
return Utility.randomString(6,"abcdefghijklmnopqrstuvwxyz")
}
//Check if the code is unique
function checkCode(code) {
return new Promise(function (resolve, reject){
Url.findOne({code:code}, function(err, data) {
if(err === null){
resolve(code)
}else if(data){
saveUrlCode(getCode())
}
})
})
}
My earlier route which was :
app.get('*', function (request, response, next){
response.sendFile(path.resolve(__dirname, '../client', 'index.html'))
next()
})
The get route was getting executed twice on account of the above call and the
app.get(":/code") call.
So I had to handle the routes properly which I have done by handling the dashboard and about routes separately instead of using the "*" route.

Resources