First off, I read all other StackOverflow answers and GitHub Issues and none of them seem to have solved my problem. With the following code (some of it is deprecated, sorry for the dirty code):
var express = require('express');
var fs = require('fs');
var path = require('path');
var parser = require('body-parser');
//Initializing the Express Framework
const app = express();
const mongoose = require('mongoose');
const uuidv4 = require ('uuid/v4');
var jose = require('node-jose');
var secureRandom = require('secure-random');
var bcrypt = require('bcrypt');
const jwt = require('express-jwt');
const jwt2 = require('jsonwebtoken');
var userSchema = new mongoose.Schema({
username: {type:String,unique:true},
password: String
},{timestamps:true})
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
var signingKey = secureRandom(256, {type: 'Buffer'});
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Add headers
app.use(function (req, res, next) {
res.removeHeader('X-Powered-By');
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,Authorization');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
var claims = {
iss: "http://example.com/", // The URL of your service
sub: "users/admin1", // The UID of the user in your system
name: "User Name",
scope: "self, admins"
}
userSchema.pre('save', function (next) {
var user = this;
if (!user.isModified('password')) {return next()};
bcrypt.hash(user.password,10).then((hashedPassword) => {
user.password = hashedPassword;
next();
})
}, function (err) {
next(err);
})
userSchema.methods.comparePassword=function(candidatePassword,next){ bcrypt.compare(candidatePassword,this.password,function(err,isMatch){
if(err) return next(err);
next(null,isMatch)
})
}
module.exports = mongoose.model("user", userSchema);
function protectRoute(req,res,next){
// if user exists the token was sent with the request
if(req.user){
//if user exists then go to next middleware
next();
}
// token was not sent with request send error to user
else{
res.status(500).json({error:'login is required'});
}
}
/* app.get('/protected',
jwt({secret: 'shhhhhhared-secret'}),
function(req, res) {
if (!req.user.admin) return res.sendStatus(401);
res.sendStatus(200);
}); */
MongoClient.connect(url, {
useUnifiedTopology: true,
useNewUrlParser: true,
},function(err, db) {
if (err) throw err;
var dbo = db.db("demo");
dbo.collection("demo").find({}).toArray(function(err, result) {
if (err) throw err;
console.log(result);
db.close();
});
});
readJsonFile = function(fname, res) {
fs.readFile(fname, 'utf8', function (err,data) {
if (err) {
console.log(err);
}
res.send(data.toString().replace(/\n|\r/g,''));
});
}
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.get('/users', function (req, res) {
MongoClient.connect(url, {
useUnifiedTopology: true,
useNewUrlParser: true,
},function(err, db) {
if (err) throw err;
var dbo = db.db("demo");
dbo.collection("users").find({}).toArray(function(err, result) {
if (err) throw err;
res.send(result);
db.close();
});
});
console.log("GET UserCollection from MongoDB");
});
app.post('/users/:id', verifyToken, function (req, res){
jwt2.verify(req.token, 'secretkey', (err, auth) =>{
if(err){
res.sendStatus(403);
} else {
res.json({
message: 'User created (in theory)',
authData
})
}
})
res.json({
message: 'User created (in theory)2'
})
});
app.post('/api/login', function (req, res){
// Mock user TODO: implement proper BackEnd!
const user = {
id:1,
username:'brad',
email: 'brad@gmail.com'
}
jwt2.sign({user}, 'secretkey', { expiresIn: '1h'}, (err, token) =>{
res.json({
token
});
});
});
app.get('/user', function (req, res) {
readJsonFile('user.json', res);
console.log("GET User");
});
// FORMAT OF TOKEN
// Authorization: Bearer <access_token>
// Verify Token
function verifyToken(req, res, next){
// Get auth header value
const bearerHeader = req.headers['authorization'];
// Check if bearer is undefined
if(typeof bearerHeader !== 'undefined'){
// Split at the space
const bearer = bearerHeader.split(' ');
// Get token from array
const bearerToken = bearer[1];
// Set the token
req.token = bearerToken;
// Next middleware
next();
res.json({message: "Login successful"});
}
else{
// Forbidden
res.sendStatus(403);
next();
}
}
app.listen(3000, function () {
console.log('Listening on port 3000!');
});
if(process.env.NODE_ENV !== 'production') {
process.once('uncaughtException', function(err) {
console.error('FATAL: Uncaught exception.');
console.error(err.stack||err);
setTimeout(function(){
process.exit(1);
}, 100);
});
}
After I run the app and POST the URL /users/5 I get the following errors and the app crashes:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:485:11)
at Array.write (C:\Users\User\Documents\Project\Project2\node_modules\finalhandler\index.js:285:9)
at listener (C:\Users\User\Documents\Project\Project2\node_modules\on-finished\index.js:169:15)
at onFinish (C:\Users\User\Documents\Project\Project2\node_modules\on-finished\index.js:100:5)
at callback (C:\Users\User\Documents\Project\Project2\node_modules\ee-first\index.js:55:10)
at IncomingMessage.onevent (C:\Users\User\Documents\Project\Project2\node_modules\ee-first\index.js:93:5)
at IncomingMessage.emit (events.js:215:7)
at endReadableNT (_stream_readable.js:1183:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
ReferenceError: authData is not defined
at C:\Users\User\Documents\Project\Project2\src\app.js:134:9
at C:\Users\User\Documents\Project\Project2\node_modules\jsonwebtoken\verify.js:223:12
at getSecret (C:\Users\User\Documents\Project\Project2\node_modules\jsonwebtoken\verify.js:90:14)
at Object.module.exports [as verify] (C:\Users\User\Documents\Project\Project2\node_modules\jsonwebtoken\verify.js:94:10)
at C:\Users\User\Documents\Project\Project2\src\app.js:127:8
at Layer.handle [as handle_request] (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\route.js:137:13)
at verifyToken (C:\Users\User\Documents\Project\Project2\src\app.js:178:5)
at Layer.handle [as handle_request] (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:281:22
at param (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:354:14)
at param (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:365:14)
at Function.process_params (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:410:3)
I tried adding return and next statements without any avail.
P.S This helps to understand the problem:
This error occurs when you sent a response before and then you try to send response again. For this you have to check if there is any piece of code that is sending your response twice. Sometimes it happens due to asynchronous behavior of nodejs. Sometimes a process will be in event loop and we send response and when it finishes execution response will be sent again. So You can use callbacks or async await to wait for execution.
PP.S After following the code examples given in the answers now I get this error (it's more similar to the linked question now):
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:485:11)
at ServerResponse.header (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\response.js:267:15)
at verifyToken (C:\Users\User\Documents\Project\Project2\src\app.js:176:9)
at Layer.handle [as handle_request] (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:281:22
at param (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:354:14)
at param (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:365:14)
at Function.process_params (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:410:3)
at next (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\index.js:275:10)
at C:\Users\User\Documents\Project\Project2\src\app.js:35:3
at Layer.handle [as handle_request] (C:\Users\User\Documents\Project\Project2\node_modules\express\lib\router\layer.js:95:5)