0
votes

Here is my index.js code

var express = require("express");
var mysql = require('mysql');
var pug = require('pug');
var bodyparser = require('body-parser');
var app = express();

var conn = mysql.createConnection({
    host: "remotemysql.com",
    user: "",
    password: "",
    database: ""
});

conn.connect(function(err) {
    if (err) {
        console.log("Error connecting to MySQL:", err);
    } else {
        console.log("Connection established");
    }
});

let people = [];
let i = 0;

let subname = null;
let subemail = null;
let subsession = null;

app.set("views", "views");
app.set("view engine", "pug");
app.use(express.static("public"));
app.use(bodyparser());

app.get("/", function(req, res, next) {
    res.render("confirmed");
});

app.post("/register", function(req, res, next) {

    var attendees = {
        name: req.body.name,
        email: req.body.email,
        session: req.body.selectpicker
    };
    conn.query("INSERT INTO attendees SET ?", attendees, function(err, result, ) {
        if (err)
            res.send(err);
        else
            res.send("Thank You for registering!");
    });

    if (i = 0) {
        people.pop();
    }

    subname = req.body.name;
    subemail = req.body.email;
    subsession = req.body.session;

    let locals = {
        name: subname,
        email: subemail,
        session: subsession
    };
    people.push(subname + "," + subemail + "," + subsession);

    console.log(locals);
    console.log(subname);
    console.log(subemail);
    console.log(subsession);
    console.log("People: " + people);

    res.render("confirmed", locals);
});

//app.post("/register", function(req, res) {
//});

app.get("/list", function(req, res, next) {
    let peoplelist = {
        attendeelist: people
    }
    res.render("list", peoplelist);
});

app.listen(3000);

I keep getting the error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ServerResponse.setHeader (_http_outgoing.js:526:11) at ServerResponse.header (/home/runner/M18-CloudSecConf-with-DB/node_modules/express/lib/response.js:771:10)

what do i need to change, move, or add to get this to go away. I understand somewhat that it is trying to send data to the server and then can't set the headers but I'm not sure what to do. Please help, trying to learn this stuff.

1
Pretty simple really. You are calling both res.send() and res.render() in the same request handler. You get to send only ONE response per request. Pick one of the other, not both. This particular error is the http engine tell you that you're trying to send the headers for a response, but you've already sent the response. The error would be a bit more helpful if it said: "http response already sent, can't send another one". - jfriend00
I fixed it, I appreciate it, I've been looking at this code for like 30 minutes now trying to figure out why it was happening. This is all new to me, so I appreciate the help. But yes the errors are not helpful sometimes at explaining why. - adamb
If you want, you can answer your own question by posting an answer that shows and explains the solution. But, you do that by posting a separate answer, not by editing your question. - jfriend00
Sorry for that, I realized after the post that I didn't add the updated code, apologies. Won't happen again! - adamb

1 Answers

0
votes

Your /register route handler has a res.send() inside the database callback and it also has a res.render() at the end of the route handler. Each of those attempts to send a request to the incoming http request. But, you can only send ONE http response for each http request.

Express notices this problem at the very beginning of the second attempt to send a response and it notices this when it's trying to gather the headers to send for the second response and it sees that the headers have already been sent, thus the message you get.

So, you need to remove either the res.send() or the res.render() or somehow combine them into one response.

The relevant route handler is this one:

app.post("/register", function(req, res, next) {

    var attendees = {
        name: req.body.name,
        email: req.body.email,
        session: req.body.selectpicker
    };
    conn.query("INSERT INTO attendees SET ?", attendees, function(err, result, ) {
        // ATTEMPT #1 to send a response
        if (err)
            res.send(err);
        else
            res.send("Thank You for registering!");
    });

    if (i = 0) {
        people.pop();
    }

    subname = req.body.name;
    subemail = req.body.email;
    subsession = req.body.session;

    let locals = {
        name: subname,
        email: subemail,
        session: subsession
    };
    people.push(subname + "," + subemail + "," + subsession);

    console.log(locals);
    console.log(subname);
    console.log(subemail);
    console.log(subsession);
    console.log("People: " + people);

    // ATTEMPT #2 to send a response
    res.render("confirmed", locals);
});

FYI, your if statement:

    if (i = 0) {

is not correct. That assigns 0 to the i and then does the if on the result of the assignment which is not what you want. A proper if statement would be:

    if (i === 0) {

It's also unclear what you're trying to do with a generically named module-level variable like i that is shared among all users and all requests. That is probably an incorrect design also.

Similarly, variables like subname, subemail, subsession should be declared locally inside your route handler, not at the module level.

Remember that any variable declared outside a route handler is shard by all users and all routes and that is not what you usually want except for lasting state that is shared globally by all users and all routes on the server.