简体   繁体   中英

express.js - how to intercept response.send() / response.json()

Lets say I have multiple places where I call response.send(someData) . Now I want to create a single global interceptor where I catch all .send methods and make some changes to someData . Is there any way in express.js? (hooks, listeners, interceptors, ...)?

You can define a middleware as below (taken and modified from this answer )

function modifyResponseBody(req, res, next) {
    var oldSend = res.send;

    res.send = function(data){
        // arguments[0] (or `data`) contains the response body
        arguments[0] = "modified : " + arguments[0];
        oldSend.apply(res, arguments);
    }
    next();
}

app.use(modifyResponseBody);

for those finding on google, based off the top answer:

app.use((req, res, next) => {
    let oldSend = res.send
    res.send = function(data) {
        console.log(data) // do something with the data
        res.send = oldSend // set function back to avoid the 'double-send'
        return res.send(data) // just call as normal with data
    }
    next()
})

Yes this is possible. There are two ways to do this, one is to use a library that provides the interception, with the ability to run it based on a specific condition: https://www.npmjs.com/package/express-interceptor

The other option is to just create your own middleware (for express) as follows:

function modify(req, res, next){
  res.body = "this is the modified/new response";

  next();
}
express.use(modify);

Just want to provide a practical usage example with intercepting res.json .

When we're writing express server, we might send the status and message in every response according to the situation like below.

app.post('/test', (req, res) => {
    res.json({status: 1, message: "some_error", otherData: "nothing"})
})

But, what if I don't want to write the status and message in every time? I could add new function to build a template response body to send the data when using res.json .

const messageMap = {
    0: "success",
    1: "some_error"
}

app.use((req, res, next) => {
    const originJson = res.json
    res.json = (status, jsonData) => {
        const fixedResponse = {
            status,
            message: messageMap[status]
        }
        originJson.call(res, {...jsonData, ...fixedResponse})
    }
    next()
})

Then I just need to use below function.

app.get("/test", (req, res) => {
    res.json(1, {otherData: 1})
})

You can even use builder pattern to do this.

app.use((req, res) => {
    res.buildFixedResponse = function (status)  {
        const fixedResponse = {
            status,
            message: messageMap[status]
        }
        res.json = function (jsonData) {
            originJson.call(this, {...jsonData, ...fixedResponse})
        }
        return this
    }
})

Then trigger function like below.

app.get("/test", (req, res) => {
    res.buildFixedResponse(1).json({otherData: 1})
})

For my case, I had to use a middleware with typicode/json-server and be able to get a different response object than just a blunt javascript array.

While the typicode/json-server response was something like:

[
 {
   ...
 }
]

After applying the middleware:

module.exports = (req, res, next) => {
 const oldSend = res.send;
 res.send = (data) => {
  const oldData = JSON.parse(data);
  // we want to change the response only if a blunt array is sent
  // also, we do this for the old sake of not sending json arrays
  if(Object.prototype.toString.call(oldData) === '[object Array]') {
   data = {
    data: oldData
   };
  }
  res.send = oldSend;
  return res.send(data);
 };
 next();
}

The response looks as follows:

 {
  data: [
   {
    ...
   }
  ]
 }

You can simply do it using NODEJS and Express, say you are calling an API and want to send modify the data before sending response back.

router.get('/id', (req,res) => {
... //your code here filling DATA

  let testData = {
    "C1": "Data1",
    "C2": "Data2",
    "yourdata": DATA
  };          
  res.send(testData);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM