No matter how I set the res.format() in Express, the data is always parsed depending on the parse method of fetch(). Why?

Issue

I am not understanding how does the res.format() work. I read all the documentation, plus several answers here on stackoverflow, but they don’t actually address the part that confuses me.

app.get('/', (req, res) => {

     res.format({
         'text/html' : function() { 
             res.send({name: 'romeo'})
         }
     })
})

In the above example, I am setting the format to be 'text/html', but I am actually sending a JS object.

So, now, in the client side:

        fetch(req)
        .then(res=>res.json())
        .then(content=> {
            //output.innerHTML = JSON.stringify(content, '\n', 2);
            console.log(content)
            output.innerHTML = content;
        }) 
        .catch(err=>console.eror);

If I use json(), the data will just get parsed into a JS object no matter what I send, and no matter what I set the res.format() to be. Why? This is what I don’t get.

Even if I set the format to be 'application/json', I can just send a plain text, and then if I use json() again, it will again return a JS object.

And vice versa, if I send a JS object, but use text() instead, it will get parsed into text.

So, what exactly does the format do?

Yes, I read that It’s supposed to check the Accept in the HTTP request header, and then invoke corresponding handler according the Accept value, but that doesn’t really tell me anything. I am not setting a request header, and no matter how I set the format(), the actual format of the data is always determined by the parsing method I choose to use json() for JS object, or text() for text or html. I don’t see the purpose of setting a format().

Solution

res.format(object) is used such that the client can specify what type of content they want returned. The client specifies this information using the Accepts header on their request.

To read more about res.format(object) visit https://expressjs.com/en/5x/api.html#res.format

To read more about the Accepts header visit https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept

Below I created a simple example of what this would look like

Server code

const express = require("express");

const PORT = process.env.PORT || 5000;
const app = express();

app.get('/', function (req, res) {
  res.format({
    'text/plain': function () {
      res.send('text')
    },
  
    'text/html': function () {
      res.send('<p>html</p>')
    },
  
    'application/json': function () {
      res.send({ message: 'json' })
    },
  })
})

app.listen(PORT, () => {
  console.log("Listening on port: " + PORT);
}); 

Client Code

const fetch = require("node-fetch");

fetch('http://localhost:5000/', {
  headers: {
    'Accept': 'text/html'
  }
})
.then(res => res.text())
.then(res => {
  console.log(res) // <p>html</p>
});

fetch('http://localhost:5000/', {
  headers: {
    'Accept': 'text/plain'
  }
})
.then(res => res.text())
.then(res => {
  console.log(res) // text
});

fetch('http://localhost:5000/', {
  headers: {
    'Accept': 'application/json'
  }
})
.then(res => res.json())
.then(res => {
  console.log(res) // { message: 'json' }
});

Answered By – Hans Krohn

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published