1
votes

Preamble: I'm new to web dev so maybe this might be a very basic question for you vets.

I'm using MVC architecture pattern for this basic app. I've models (MongoDB), views (Express Handlebars), and controllers (functions that take in req, res, next and returns promises (.then > JSON is returned, .catch > error is returned). I'll be routing the paths reqs to their corresponding api endpoints in the controllers.

This makes sense (right?) when I'm purely working on API calls where JSON is the res. However, I also want to call these api endpoints > get their res.json > and use that to render my HTML using Handlebars. What is the best way to accomplish this? I can create same controllers and instead of resp being JSON, I can do render ("html view", res.json). But that seems like I'm repeating same code again just to change what to do with the response (return JSON or Render the JSON).

Hope I'm making sense, if not, do let me know. Please advise.

p.s. try to ELI5 things for me. (:

Edit:

//Model Example
const Schema = require('mongoose').Schema;

const testSchema = new Schema({
    testText: { type: String, required: true },
});

const Test = mongoose.model('Test', testSchema);

module.exports = Test;


//Controller Example
const model = require('../models');

module.exports = {
    getAll: function(req, res, next) {
        model.Test.find(req.query)
            .then((testItems) => {
                !testItems.length
                    ? res.status(404).json({ message: 'No Test Item Found' })
                    : res.status(200).json(testItems);
            })
            .catch((err) => next(err));
    },
};

//Route Example
const router = require('express').Router(),
    controller = require('../controllers');

router.get('/', controller.getAll);

module.exports = router;

I want the endpoints to return JSON and somehow manage whether to render (if the req comes from a browser) or stay with JSON (if called from Postman or an API web URL for example) without repeating the code. I'm trying to not create two endpoitns with 99% of the code being the same, the only difference being .then > res.status(200).json(testItems); vs .then > res.status(200).render('testPage', { testItems}).

2
render('view', {}) seems to me quite logical if you want specific data in a specific view.Moad Ennagi
Hi welcome to SO... At first, the question you're asking is too broad. You should share the part of code representing your problem (the controller file for exemple - if not your question will be closed)... welcome link After yes, you can create two routes to go on the same controller action... and check the path for exemple... if it's ending by .json you call the res.json(...)BENARD Patrick
@MoadEnnagi, I want to somehow call the same endpoint that returns JSOn and be able to show just the JSON (in postman for example) or view that JSON rendered on the app (using express handlebars). I'm struggling with doing these 2-for-1 sorta thing without needing to write two controllers, one that res.json and other that render("view",{}) for the same request.007
@PimentoWeb added a test code. What do you mean by the last thing you mentioned? can you please show an example code or something so I can understand it better? This sounds interesting.007
Hi, just to be clear you want you endpoints to return json if its from postman and html page if its from brower ?warl0ck

2 Answers

0
votes

For postman you could check the existence of postman-token in req.headers, then you could render accordingly, something like this:

req.headers['postman-token'] ? res.json({ /* json */ }) : render('view', {/ * json */});
0
votes

If you want to go with checking postman token then you can use similar to method1.

if you want to check with query params in this case you can get json response or html even from browser for future use also and is not dependent on postman then use similar to method2 of the following example.

const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
const port = 5000



app.get('/method1', (req, res) => {
  const isJSONResp = req.headers['postman-token']
  const resp = { status: "hello" }
  if (isJSONResp) {
    res.json(resp)
  } else {
    res.render('some.html', resp)
  }
})

app.get('/method2', (req, res) => {
  const params = req.params
  const resp = { status: "hello" }
  if (params.resp === 'json') {
    res.json(resp)
  } else {
    res.render('some.html', resp)
  }
})

app.listen(port, () => console.log(`Example app listening on port ${port}!`))