0

I wrote a simple CRUD Api in node.js. I keep getting a write after end on all of my POST, PUT and DELETE functions. I have lost all sense of trying to trouble shoot this thing and was hoping for a fresh pair of eyes or some advice on trying to track it down. GET works perfectly fine and uses the same code sendJSON() in httpmgs.js.

I have scattered all kinds comments around trying to figure out where the error is happening. I didn't know if the req.on("end".... was causing an issue so I have rewritten that part to no avail.

controller.js:

 switch (req.method){
    case "GET":
          if(req.url === "/staff"){
            staff.getList(req, resp);
        }
        break;
    case "POST":
      if (req.url === "/staff/add"){
            var reqBody = '';
            req.on("data", function (data){
                reqBody += data;
                if(reqBody.length > 1e7){
                    msg.show413(req, resp);              
                }
            });
            req.on("end", function() {
                console.log(req.data)
                staff.add(req, resp, reqBody)
            });            
        }
        break;
    case "PUT":
        if (req.url === "/staff/update"){
            var reqBody = '';
            req.on("data", function (data){
                reqBody += data;
                if(reqBody.length > 1e7){
                    msg.show413(req, resp);
                }
            });
            req.on("end", function() {
                staff.update(req, resp, reqBody);
            });

        }
        else{
            msg.show404(req,resp);
        }
        break;

staff.js:

exports.add = function (req, resp, reqBody){
    try{
        if (!reqBody) throw new Error("Input not valid");
        var data = JSON.parse(reqBody);
        if (data){

            db.executeSql("SELECT MAX(ID) AS ID FROM jarvisdb.staff",function (maxID, err){
                if(err){
                    msg.show500(req, resp, err);
                }
                else{
                    var newID = maxID[0].ID+1
                    var sql = "INSERT INTO jarvisdb.staff (`ID`, `First Name`, `Last Name`) VALUES";
                    sql+= util.format("('%d' ,\"%s\", \"%s\")", newID, data.firstName, data.lastName); 
                    db.executeSql(sql, (data, err)=>{
                        if(err){
                            msg.show500(req, resp, err)
                        }
                        else{
                            console.log('Before send')
                            msg.sendJSON(req,resp,data)
                            console.log('After send')
                        }
                    })

                }
            });
        }
        else{
            throw new Error("Input not valid");
        }
    }
    catch (ex) {
        console.log('500')
        msg.show500(req, resp, ex);

    }
};

httpMsgs.js:

exports.sendJSON = function(req,resp,data){
    if(data){
        console.log('Before Write')
        resp.writeHead(200, {"Content-type" : "application/json"});
        console.log('Write Head')
        resp.write(JSON.stringify(data));
        console.log('Write body')
        resp.end();
        console.log('end');
    }
}

Expected out: No errors and sends back JSON

Actual results:

Listening on port 9000....
undefined
Before send
Before Write
Write Head
Write body
end
After send
events.js:174

      throw er; // Unhandled 'error' event
      ^

Error [ERR_STREAM_WRITE_AFTER_END]: write after end
    at write_ (_http_outgoing.js:572:17)
    at ServerResponse.write (_http_outgoing.js:567:10)
    at Object.exports.sendJSON (E:\JARVIS\API\peak-2.0\httpMsgs.js:60:14)
    at db.executeSql (E:\JARVIS\API\peak-2.0\controllers\staff.js:53:33)
    at Execute.conn.execute [as onResult] (E:\JARVIS\API\peak-2.0\db.js:35:9)
    at process.nextTick (E:\JARVIS\API\peak-2.0\node_modules\mysql2\lib\commands\query.js:76:16)
    at process._tickCallback (internal/process/next_tick.js:61:11)
Emitted 'error' event at:
    at writeAfterEndNT (_http_outgoing.js:634:7)
    at process._tickCallback (internal/process/next_tick.js:63:19)
AjDed
  • 17
  • 4

1 Answers1

0

There is no break; after your case. So, all cases beyond the current matched case will be executed sequentially until the end.

EDIT

Try restarting your SQL server

UPDATE

You have two options : In your sendJSON function use:

OPTION 1 (Without Express):

resp.writeHead('Content-Type', 'application/json'); resp.end(JSON.stringify(data));

OR

OPTION 2 (With Express): Here you don't need to specify the header type

res.json(data);

Aakshaye
  • 359
  • 1
  • 3
  • 17
  • Sorry the breaks are there in the actual code. This is just a snippet. I will edit the question – AjDed Aug 09 '19 at 16:48
  • Can you also add file names so the error messages can be better understood? – Aakshaye Aug 09 '19 at 16:55
  • The only piece of code missing from the error that I wrote is db.js which just makes the mysql database calls. – AjDed Aug 09 '19 at 17:11
  • Restarting didn't help. – AjDed Aug 09 '19 at 17:15
  • Have you looked at this ? https://stackoverflow.com/questions/19357539/node-js-server-closed-the-connection – Aakshaye Aug 09 '19 at 17:27
  • Aakshaye, that question was helpful but it didn't fix my problem because my get code still works great. So it is not an issue with the sql or its connection to the database. It is only an issue with the html response. – AjDed Aug 09 '19 at 18:46
  • I'm sorry, but your console logs indicated that there was a mysql connection issue. If that is not the case, you should try `console.log` the actual `data` . – Aakshaye Aug 11 '19 at 00:03
  • Were you able to solve the problem? If yes, can you please let us know what was wrong? – Aakshaye Aug 12 '19 at 20:03
  • With the new code Aakshaye suggested this is the the error: _http_outgoing.js:470 throw new ERR_HTTP_HEADERS_SENT('set'); ^ Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:470:11) at Object.exports.sendJSON (E:\JARVIS\API\peak-2.0\httpMsgs.js:65:14) at db.executeSql (E:\JARVIS\API\peak-2.0\controllers\staff.js:53:33) at Execute.conn.execute [as onResult] (E:\JARVIS\API\peak-2.0\db.js:35:9) at process.nextTick ... – AjDed Aug 13 '19 at 17:58
  • The only change I had to make to Aakshaye updated suggestions is instead of using : ``` resp.setHeader() ``` to: ``` resp.writeHead() ``` – AjDed Aug 13 '19 at 18:05
  • I'll update the answer so that it helps someone else – Aakshaye Aug 13 '19 at 21:45