36

I would like to have a middleware function which modifies the response body.

This is for an express server.

Something like:

function modify(req, res, next){
  res.on('send', function(){
    res.body = res.body + "modified"
  });

  next();
}

express.use(modify);

I don't understand what event to listen for. Any help or documentation would be appreciate.

Chenmunka
  • 685
  • 4
  • 21
  • 25
The Who
  • 6,552
  • 5
  • 36
  • 33

5 Answers5

27

You don't need to listen to any events. Just make it

function modify(req, res, next){
  res.body = res.body + "modified";

  next();
}

And use it after you use the router. This way after all your routes have executed you can modify the body

Christopher Tarquini
  • 11,176
  • 16
  • 55
  • 73
  • 5
    I am trying to use my middleware after the router, but it seems to be not triggered at all. It is only triggered if I use it before app.router. I am using it insite the app.configure block, if that makes any difference. – ragulka Oct 24 '12 at 21:02
  • 10
    Make sure you are calling `next` in your routes, otherwise express won't execute any middleware after that route – Christopher Tarquini Sep 29 '13 at 15:27
  • what exactly means "after you `use` the router"? In a simple app with `app.get(someRoute, handler)`s and `app.listen(port, anotherHandler`, do I have to `app.use(modify)` after `app.listen`? For me both before and after it seems not to work (I added `app.use((req, res, next) => { console.log('after response'); next(); })` and don't see anything in console.. – YakovL May 02 '21 at 15:37
  • 1
    Not working for express 4, there is no such an property or method called `body` of `Response` object according to [api doc](https://expressjs.com/en/4x/api.html#res) – sam Jan 27 '22 at 02:36
21

I believe the OP actually wants to modify the response stream once a middleware has handled the request. Look at the bundled Compress middleware implementation for an example of how this is done. Connect monkey patches the ServerResponse prototype to emit the header event when writeHead is called, but before it is completed.

Corey Jewett
  • 311
  • 2
  • 3
13

express-mung is designed for this. Instead of events its just more middleware. Your example would look something like

const mung = require('express-mung')

module.exports = mung.json(body => body.modifiedBy = 'me');
Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
10

Overwriting the response's write method seemed to work for me with Express 4. This allows modifying the response's body even when it's a stream.

app.use(function (req, res, next) {
  var write = res.write;
  res.write = function (chunk) {
    if (~res.getHeader('Content-Type').indexOf('text/html')) {
      chunk instanceof Buffer && (chunk = chunk.toString());
      chunk = chunk.replace(/(<\/body>)/, "<script>alert('hi')</script>\n\n$1");
      res.setHeader('Content-Length', chunk.length);
    }
    write.apply(this, arguments);
  };
  next();
});

Just make sure to register this middleware before any other middleware that may be modifying the response.

Peleg
  • 1,204
  • 10
  • 8
  • 3
    To simplify your answer a bit instead of `~res.getHeader('Content-Type').indexOf('text/html')` you may use `res.getHeader('Content-Type').indexOf('text/html') > -1` – jmarceli Jul 31 '19 at 21:24
2

There seems to be a module for doing just this called connect-static-transform, check it out:

https://github.com/KenPowers/connect-static-transform

A connect middleware which allows transformation of static files before serving them.

And it comes with examples, like this one.

Greg Slepak
  • 1,613
  • 16
  • 17
  • Unfortunately the `transform` callback of this middleware does not receive the `req` and `res` arguments from the middleware chain. – Evgeny Aug 11 '21 at 15:03