简体   繁体   中英

NodeJS - Getting error “Can't set headers after they are sent”

I am new to node and I am building rest node API.I am using express for HTTP and JWT for authentication. Whenever I request /node/me with header 'x-auth'. It's giving error which is given below. I have set up middleware in /node/me which query mogodb database. It finds user using header 'x-auth'

server.js:

var env = process.env.NODE_ENV || 'development';
if (env === "development") {
    process.env.PORT = 3000;
    process.env.MONGODB_URI = 'mongodb://localhost:27017/TodoApp';
} else if (env === "test") {
    process.env.PORT = 3000;
    process.env.MONGODB_URI = 'mongodb://localhost:27017/TodoAppTest';
}
var _ = require('lodash');
var express = require('express');
var bodyParser = require('body-parser');
var {ObjectID} = require('mongodb');
var app = express();

var {mongoose} = require('./db/mongoose');
var {Todo} = require('./models/todo');
var {User} = require('./models/user');
const {authenticate} = require('./middleware/authenticate');
const bcrypt = require('bcryptjs');
const port = process.env.PORT;

app.use(bodyParser.json());
app.get('/users/me',authenticate,(req,res) => {
    res.send(req.user);
});
module.exports = {
    app,
    env
}

app.listen(port,() => {
    console.log(`server is running ${port}`);
});

authenticate.js:

const {User} = require('./../models/user');
var authenticate = (req,res,next) => {
var token = req.header('x-auth');
User.findByToken(token).then((doc) => {
    if (!doc) {
       res.status(401).send('doc is not found');
    }
    req.token = token;
    req.user = doc;
    next();
}).catch((e) => {
    res.status(401).send(e);
});

I am getting this error about headers

 Error: Can't set headers after they are sent.
    at validateHeader (_http_outgoing.js:494:11)
    at ServerResponse.setHeader (_http_outgoing.js:501:3)
    at ServerResponse.header (C:\Users\Yash\Desktop\node-api\node_modules\express\lib\response.js:719:10)
    at ServerResponse.send (C:\Users\Yash\Desktop\node-api\node_modules\express\lib\response.js:164:12)
    at app.get (C:\Users\Yash\Desktop\node-api\server\server.js:254:5)
    at Layer.handle [as handle_request] (C:\Users\Yash\Desktop\node-api\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\Yash\Desktop\node-api\node_modules\express\lib\router\route.js:131:13)
    at User.findByToken.then (C:\Users\Yash\Desktop\node-api\server\middleware\authenticate.js:19:2)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

You must change to this:

if(!doc) {
    res.status(401).send('doc is not found');
} else {
    req.token = token;
    req.user = doc;
    next();
}

The reason is after the if inside code is executed the flow continues independently if you are sending a response because it is just a function call. So you are executing the error code and after that you are executing the success code, I mean the next function like if the doc exists and at the moment of the next() execution the response has been sent.

Regards,

You can only send one response with express. If you follow the series of events in your Authenticate middleware you'll discover that you are sending a response with:

res.status(401).send('doc is not found');

and then calling next() . When you call next it passes control over to the next middleware, which then sends:

res.send(req.user);

Cut the next() out of the loop when the request fails with something like:

if(!doc){
    res.status(401).send('doc is not found');
    return;
}

You must export authenticate. And add return

if(!doc) {
    res.status(401).send('doc is not found');
    return;
}

or add else

if(!doc) {
    res.status(401).send('doc is not found');
  } else {
      req.token = token;
      req.user = doc;
      next();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM