Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

res.json Can't set headers after they are sent

Tags:

I'm learning node Js and i'm trying to do a simple subscribe/log_in app. I'm having issue with res.json not working as intended.

Got this error when i'm trying to subscribe : Can't set headers after they are sent

This is my server side script :

var express = require('express'); var swig = require('swig'); var ent = require('ent'); var bodyParser = require('body-parser'); var mongoose = require('mongoose'); var session = require('express-session');  var app = express();  // Environnement app.set('port', process.env.PORT || 3000); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use("/public", express.static(__dirname + "/public")); app.engine('html', swig.renderFile); app.set('view engine', 'html'); app.set('views', __dirname + '/views'); app.set('view cache', false); swig.setDefaults({ cache: false }); app.use(session({     secret: 'poussixthetruefighteroftheparadise',     saveUninitialized: true,     resave: true }));  //MongoDB var db = mongoose.connect('mongodb://127.0.0.1:27017/maBase'); var userSchema = new mongoose.Schema({     login:  String,     mail: String,     password: String }); var user = db.model('user', userSchema)  // variables globales var state;     // Page Principale app.get('/', function(req,res){      if (req.session.user) {         res.render('accueil.html',{});     } else {         res.redirect('/connection');     }  });  // Page connection app.route('/connection')     .get(function(req, res) {          res.render('index.html',{});          if (req.session.state) {             res.json({state: req.session.state});         }      })     .post(function(req, res) {          user.find({login: req.body.login, password: req.body.password}).limit(1).exec(function (err, users) {              if (err) { console.log(err) };              if (!users.length) {                  console.log('connection pas ok');                  res.json({state: '5'});              }             else {                  console.log('connection ok');                 res.redirect('/');              }          });      });   // Ajouter Utilisateur app.post('/connection/ajouter', function(req,res){      var login = req.body.login;     var mail = req.body.mail;      user.find({$or: [{login: login}, {mail: mail}]}).limit(1).exec(function (err, users) {          if (err) { console.log(err) };          if (!users.length) {              console.log('login et mail ok');              if (req.body.password == req.body.password2) {                  if (req.body.password.length > 6) {                      var values = new user({                             login: ent.encode(req.body.login),                             mail: ent.encode(req.body.mail),                             password: ent.encode(req.body.password)                     });                      values.save(function(err, values) {                          if (err) return console.error(err);                          console.log('utilisateur enregistré');                          req.session.state = '6';                         res.redirect('/connection');                      });                  } else {                      console.log('Mot de passe trop court');                      req.session.state = '3';                     res.redirect('/connection');                  }               } else {                  console.log('mot de passe différent');                  req.session.state = '4';                 res.redirect('/connection');              }          }          else {              console.log('login ou mail déja utilisé');              if (users[0].mail == mail) {                  console.log('mail déja utilisé');                 req.session.state = '2';                 res.redirect('/connection');              } else {                  console.log('login déja utilisé');                 req.session.state = '1';                 res.redirect('/connection');              }              console.log(users);          }      });  });     app.listen(app.get('port'), function(){     console.log('Express server listening on port ' + app.get('port')); }); 

And my client side script :

<html> <head>     <title>test</title>     <link rel="stylesheet" href="public/css/reset.css">     <link rel="stylesheet" href="public/css/connection.css"> </head> <body>      <div id="content">          <a href="http://localhost:3000"><img src="public/images/icone.jpg" alt="gatsbill"></a>          <div id="wrap">              <div id="espacehaut"></div>             <div class="click" id="con" style="display: block;">Se connecter</div>             <div class="click" id="sub" style="display: none;">S'inscrire</div>              <div id="connection" style="display: none;">                 <div id="message1" class="message" style="display: none;"></div>                 <form action="/connection/" method="post" id="form_connection">                     <input type="text" name="login" id="login" placeholder="Login" value="" required="" autofocus="">                     <input type="password" name="password" id="password" placeholder="Password" required="">                     <input type="submit" name="submit" value="Connect">                 </form>             </div>              <div id="subscribe" style="">                 <p id="p">Pour vous inscrire,<br> Veuillez remplir les champs ci-dessous</p>                 <div id="message2" class="message" style="display: none;"></div>                 <form action="/connection/ajouter/" method="post" id="form_inscription">                     <input type="text" name="login" placeholder="Login" value="" required="" autofocus="">                     <input type="email" name="mail" placeholder="Email" value="" required="">                     <input type="password" name="password" placeholder="Password" required="">                     <input type="password" name="password2" placeholder="Password" required="">                     <input type="submit" name="submit" value="Create account">                 </form>             </div>              <div id="espacebas"></div>          </div>     </div>      <!-- Script -->     <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>     <script type="text/javascript" src="public/js/connection.js"></script>     <script>          $.getJSON( "http://localhost:3000/connection", function(data){             if( data.state ) {                 state = parseInt(data.state);                 switch (state) {                     case 1:                         formulaire();                         $("#message2").text("login déja utilisé");                         break;                      case 2:                         formulaire();                         $("#message2").text("mail déja utilisé");                         break;                      case 3:                         formulaire();                         $("#message2").text("Mot de passe trop court");                         break;                      case 4:                         formulaire();                         $("#message2").text("mot de passe différent");                         break;                      case 5:                         connect();                         $("#message1").text("connection pas ok");                         break;                      case 6:                         connect();                         $("#message1").text("vous pouvez maintenant vous connecter");                         break;                  }             }         });      </script>  </body> </html> 

When i'm trying to subscribe with two different password this is what I have :

A white page with only this :

{"state":"4"}

And of course this error in node Js console: Can't set headers after they are sent

like image 359
Gatsbill Avatar asked Oct 10 '14 20:10

Gatsbill


People also ask

Can't set headers after they are sent?

The error "Error: Can't set headers after they are sent." means that you're already in the Body or Finished state, but some function tried to set a header or statusCode. When you see this error, try to look for anything that tries to send a header after some of the body has already been written.

How do you fix error Err_http_headers_sent ]: Cannot set headers after they are sent to the client?

To Solve Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client Here You Need To use return statement to solve this error. Error Is occurs Because Of Your res. status(400). json is executing and then your function is not going to stop.

What does res JSON () do?

json() Function. The res. json() function sends a JSON response. This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using the JSON.

What does Res send () do?

send() Send a string response in a format other than JSON (XML, CSV, plain text, etc.). This method is used in the underlying implementation of most of the other terminal response methods.


2 Answers

Welcome to nodejs/express!

This is where you are getting your "Can't set headers after they are sent" error in the console:

// Page connection app.route('/connection')     .get(function(req, res) {          res.render('index.html',{});          if (req.session.state) {             res.json({state: req.session.state});         }      }) 

In this configuration, res.render and res.json will both call res.end() which is basically like trying to send a response twice to the client.

You should place a return statement before res.render or set {state: req.session.state} as the second param to your res.render() call and then use a swig template to display that data.

like image 95
srquinn Avatar answered Sep 19 '22 11:09

srquinn


I've solved it this way:

Override res.send in the very first middleware:

app.use(function(req,res,next){     var _send = res.send;     var sent = false;     res.send = function(data){         if(sent) return;         _send.bind(res)(data);         sent = true;     };     next(); }); 
like image 40
akshay Avatar answered Sep 16 '22 11:09

akshay