Max Wolfen
Max Wolfen

Reputation: 2033

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

So I saw this great post Error: Can't set headers after they are sent to the client , but still do not understand, what is wrong with my Headers section, because when I changed it from my commented out wrong type into two separated sections:
app.use(doesNotModifyBody); app.use(doesModifyBody); (like in answer above) it does not work normally.

And for now, instead of receiving the right database answer, I always resive the string from the app.use(doesModifyBody); - res.write("<p>Hello World</p>");.

So the question, how to solve the error with the Headers in the question title and make right database answer receving, instead of res.write("<p>Hello World</p>"); P.S. deleting the res.write("<p>Hello World</p>"); is does not solve the problem.

My server code:

'use strict'
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const app = express();
const router = express.Router();
const EmployersSchemaDB = require('./SchemaDB/EmployersSchemaDB');

mongoose.connect('mongodb://myDB');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// app.use((req, res, next) => {
//     res.setHeader('Access-Control-Allow-Origin', '*');
//     res.setHeader('Access-Control-Allow-Credentials', 'true');
//     res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE');
//     res.setHeader('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers');
//     res.setHeader('Cache-Control', 'no-cache');
//     next();
// }); I change this on:

let doesNotModifyBody = (req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Credentials', 'true');
    res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers');
    res.setHeader('Cache-Control', 'no-cache');
    next();
  }; // this 
let doesModifyBody = (req, res, next) => {
    res.setHeader("Content-Type", "text/html");
    res.write("<p>Hello World</p>");
    res.end();
  }; // and this

app.use(doesNotModifyBody);
app.use(doesModifyBody);

router.get('/', (req, res) => {
    res.json({ message: 'Server is Initialized!'});
});

router.route('/employers')
    .get((req, res) => {
        EmployersSchemaDB.find((err, employers) => {
            if (err) { res.send(err) }

            res.json(employers);
        });
    })
    .post((req, res) => {
        let employer = new EmployersSchemaDB();

        employer.first_name = req.body.first_name;
        employer.last_name = req.body.last_name;
        employer.birth_date = req.body.birth_date;
        employer.salary = req.body.salary;

        employer.save((err) => {
            if (err) { res.send(err) }

            res.json({ message: 'Comment successfully added!', employer });
            console.log('---===--- \n Employer added: \n', employer + '\n ---===---');
        });  
    });

router.route('/employers/:employer_id')
    .get((req, res) => {
        EmployersSchemaDB.findById(req.params.employer_id, (err, employer) => {
            if (err) { res.send(err) }

            res.json({ message: 'Employer has been getted', employer: employer });
        });
    })
    .put((req, res) => {
        EmployersSchemaDB.findById(req.params.employer_id, (err, employer) => {
            if (err) { res.send(err) }

            (req.body.id) ? employer.id = req.body.id : null;
            (req.body.first_name) ? employer.first_name = req.body.first_name : null;
            (req.body.last_name) ? employer.last_name = req.body.last_name : null;
            (req.body.birth_date) ? employer.birth_date = req.body.birth_date : null;
            (req.body.salary) ? employer.salary = req.body.salary : null;

            employer.save((err) => {
                if (err) { res.send(err) }

                res.json({ message: 'Employer has been updated', employer: employer  });
            });
        });
    })
    .delete((req, res) => {
        EmployersSchemaDB.remove({ _id: req.params.employer_id }, (err, employer) => {
            if (err) { res.send(err) }

            res.json({ message: 'Comment has been deleted' })
        })
    });

app.use('/', router);

const port = process.env.API_PORT || 3016;
app.listen(port, () => {
    console.log(`Server running on port ${port}`);
});

Upvotes: 0

Views: 6718

Answers (2)

Dharmendra Rathod
Dharmendra Rathod

Reputation: 59

In my case, keeping catch block at the end of the function helped me fix the error as I was using redirect and render many times in my function. Here is the code

app.post("/add", async (req, res) => {
  const input = capitalizeWords(req.body["country"]).trim();
  //
  console.log('****************************************************');
  console.log(`Input : ${input}`);

  try {
    const country_code = await db.query(
      "select country_code from countries where country_name = ($1)",
      [input]
    );
    //
    console.log(
      `CHECK IF COUNTRY IS PRESENT - queried DB with ${input} and found country_code : '${JSON.stringify(
        country_code.rows
      )}'`
    );
    const data = country_code.rows[0].country_code;
    //
    console.log(`CHECK VERIFIED COUNTRY CODE - DATA - ${data}`);
    if (data){
    try {
      await db.query(
        "INSERT INTO visited_countries (country_code) VALUES ($1)",
        [country_code.rows[0].country_code]
      );
      res.redirect('/'); // keeping res here helps instead of last line in the function 
    } 
    catch (error) {
    console.error(`HANDLING DUPLICATE ENTRY: ${JSON.stringify(error)}`);
      const country_codes = await checkVisited();
      res.render("index.ejs", {
        countries: country_codes,
        total: country_codes.length,
        error: `${input} already exists in map`,
      });
    }
  } // data check ends here

  } catch (error) {
    // error message - handling wrong entry
    console.error(`HANDLING WRONG ENTRY: ${JSON.stringify(error)}`);
    const country_codes = await checkVisited();
    res.render("index.ejs", {
      countries: country_codes,
      total: country_codes.length,
      error: `Cannot find the country with name ${input}`
    });
  }
  
});

Upvotes: 0

Sello Mkantjwa
Sello Mkantjwa

Reputation: 1915

Th issue is that you are calling

res.write("<p>Hello World</p>");
res.end();

Which sends the response back to the client. Once you do this you cannot send any further data. You try to do that by calling res.json() in your middleware, which is why you want get the error that you get;

Remove BOTH the res.end and res.write lines and it should work.

Upvotes: 1

Related Questions