javascriptnode.jsexpresswebbackend

How can I render pages in conditional states in ExpressJS?


I have the following code block:

var express = require('express');

var newsRouter = express.Router();

newsRouter.get('/:news_param', (req, res) => {
    let news_params = '/haberler/' + req.params.news_param;

    req.news_list.forEach((news_obj) => {
        if (news_params == news_obj.news_addr) res.render(req.params.news_param);
    });
});

newsRouter.post('/', (req, res) => {
    res.render('news', { news_fetch_from_database: news_list });
})

newsRouter.use((req, res) => {
    res.render('404_page_news');
});

module.exports = newsRouter;

newsRouter.get('/:news_param', ...); gives the following error when I add res.redirect('/404'); like this and visit any page different than 404 page:

...

newsRouter.get('/:news_param', (req, res) => {
    let news_params = '/haberler/' + req.params.news_param;

    req.news_list.forEach((news_obj) => {
        if (news_params == news_obj.news_addr) res.render(req.params.news_param);
    });

    res.redirect('/404');
...
});
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:387:5)
    at ServerResponse.setHeader (node:_http_outgoing:644:11)
    at ServerResponse.header (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/response.js:767:10)
    at ServerResponse.location (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/response.js:884:15)
    at ServerResponse.redirect (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/response.js:922:18)
    at /home/alimkoca/Softwares/szal_web/news.js:12:9
    at Layer.handle [as handle_request] (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/router/layer.js:95:5)

And I need to handle parameters in req.params for rendering pages easily, but I can't solve this issue right now. And I don't want to use filesystem API for security issues.

I simply ran the npm start command and visited any valid page, then it gave the following error as I expressed above:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:387:5)
    at ServerResponse.setHeader (node:_http_outgoing:644:11)
    at ServerResponse.header (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/response.js:767:10)
    at ServerResponse.location (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/response.js:884:15)
    at ServerResponse.redirect (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/response.js:922:18)
    at /home/alimkoca/Softwares/szal_web/news.js:12:9
    at Layer.handle [as handle_request] (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/home/alimkoca/Softwares/szal_web/node_modules/express/lib/router/layer.js:95:5)

Solution

  • The code is always, unconditionally performing this operation:

    res.redirect('/404');
    

    Which will fail with the error given if the code has already performed this operation:

    res.render(req.params.news_param);
    

    For exactly the reason implied by the error... You can't return a response after you've already returned a response.

    It sounds like you want to only conditionally return the 404 response. For example, if no matching record was found:

    let news_params = '/haberler/' + req.params.news_param;
    let record_found = false;
    
    req.news_list.forEach((news_obj) => {
      if (news_params == news_obj.news_addr) {
        res.render(req.params.news_param);
        record_found = true;
      }
    });
    
    if (!record_found) {
      res.redirect('/404');
    }
    

    Or even just return from the function when the record is found:

    let news_params = '/haberler/' + req.params.news_param;
    
    for (let news_obj of req.news_list) {
      if (news_params == news_obj.news_addr) {
        res.render(req.params.news_param);
        return;
      }
    }
    
    res.redirect('/404');