1

I am trying to create a sub-document with my express API through postman with the following request:

POST /api/course/58c6f76e06e6edda1b000007/subject/58c6f85280a5d6591c000007/question

I am also sending x-www-forum-urlencoded data with names question and answer.

Here is the error that is output in the terminal:

Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.header (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/response.js:719:10)
at ServerResponse.send (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/response.js:164:12)
at ServerResponse.json (/home/tyler/Dropbox/Projects/Curricula/node_modules/express/lib/response.js:250:15)
at sendJSONResponse (/home/tyler/Dropbox/Projects/Curricula/API/controllers/question.js:8:8)
at Promise.<anonymous> (/home/tyler/Dropbox/Projects/Curricula/API/controllers/question.js:36:10)
at Promise.<anonymous> (/home/tyler/Dropbox/Projects/Curricula/node_modules/mpromise/lib/promise.js:171:8)
at emitOne (events.js:77:13)
at Promise.emit (events.js:169:7)
at Promise.emit (/home/tyler/Dropbox/Projects/Curricula/node_modules/mpromise/lib/promise.js:88:38)

Here is my controller file and relevant data models:

var mongoose = require('mongoose');
var Course = mongoose.model('Course');
var Subject = mongoose.model('Subject');
var Question = mongoose.model('Question');

var sendJSONResponse = function(res, status, content){
   res.status(status);
   res.json({content});
};

var addQuestion = function(req, res, subject){
  if(!subject){
    sendJSONResponse(res, 404, {"message":"subjectid not found"});
    return;
  }
  else{
    subject.questions.push({question: req.body.question,
                            answer: req.body.answer,
                            falseAnswer: req.body.falseanswer});
    subject.save(function(err, course){
      var thisQuestion
      if(err){
        sendJSONResponse(res, 400, err);
      } else{
        thisQuestion = subject.questions[subject.questions.length - 1];
        sendJSONResponse(res, 201, thisQuestion);
      }
    });
  }
}

var seekSubject = function(req, res, course){
  if(req.params && req.params.subjectid){
    Subject.findById(req.params.subjectid).exec(function(err, subject){
      if(!subject){
         sendJSONResponse(res, 404, {"message":"subjectid not found"});
      }
      else if(err){
         sendJSONResponse(res, 404, err);
         return;
      }
      sendJSONResponse(res, 200, subject);
      return subject
      });
  } else{
     sendJSONResponse(res, 404, {
        "message":"no subjectid in request"
     });
  }
};

module.exports.makeQuestion = function(req, res){
    var courseid = req.params.courseid;
    if(courseid) Course.findById(courseid).select('subjects').exec(
      function(err, course){
        if(err){
          sendJSONResponse(res, 400, err);
          return;
        }
        else var subject =  seekSubject(req, res, course);
        addQuestion(req, res, subject);
    });
}

Course Model

var mongoose = require('mongoose')
var subject = require('./subject.js');

var courseSchema = new mongoose.Schema({
   name : {type: String,
            unique: true,
            required: true},
   subjects : [subject.schema]
});

Subject Model

module.exports = mongoose.model('Course', courseSchema);

var mongoose = require('mongoose')
var question = require('./question.js');

var subjectSchema = new mongoose.Schema({
   name : String,
   questions : [question.schema]
});
module.exports = mongoose.model('Subject', subjectSchema);

Question model

var mongoose = require('mongoose')

var questionSchema = new mongoose.Schema({
   question: {type: String, required: true},
   answer: {type: String, required: true},
   falseAnswer: [String]
});

module.exports = mongoose.model('Question', questionSchema);

What am I doing wrong in creating the entry?

Tyler B. Joudrey
  • 421
  • 1
  • 8
  • 22

2 Answers2

2

It could be in this area

else var subject =  seekSubject(req, res, course);
        addQuestion(req, res, subject);

those 2 function, seekSubject and addQuestion seem like that are both calling sendJSONResponse and they both seem like that they sending a response

res.status(status); res.json({content});

So if both functions are being called in that area you are likely sending 2 responses and that is why you are getting that error.

You are doing good by separating the concerns but you got to get the error stuff separate too. your telling the server to respond twice when you call the 2 function. I think your calling both functions. I haven't ran your code.

jack blank
  • 5,073
  • 7
  • 41
  • 73
0

You get this because you are sending 2 responses when you should send just 1. Try doing the following:

res.status(500).json({ error: 'message' });

Or you might want to try using return before sendJSONResponse(res, status, content); like so for example:

return sendJSONResponse(res, 404, {"message":"subjectid not found"});

Hope this helps you out.

Codearts
  • 2,816
  • 6
  • 32
  • 54
  • I looked into this but I think the way he has it is ok . http://stackoverflow.com/a/14156612/1893672 – jack blank Mar 14 '17 at 02:53
  • 1
    @jackblank Thought so as well because at the end it is the same thing. I just use method chaining. However I think that at some point he uses sendJSONResponse twice. So that is way I suggest trying to use return. – Codearts Mar 14 '17 at 02:58