Sam Pettersson
Sam Pettersson

Reputation: 3227

Express middleware before response is carried out to client

I need to modify the response data a module sends to the client, as the module uses res.send i can't seem to figure out a way for me to modify the data before it's carried out to the client.

Is there any kind of middleware/event that I can use to catch the res.send and modify the data before its executed?

I am aware that router.use exists but it's called before the router.post function and not before the res.send is sent to the client. So I need some kind of middleware which is called after the router.post function is done but before anything is sent to the client.

Upvotes: 20

Views: 27686

Answers (4)

Fizer Khan
Fizer Khan

Reputation: 92925

It can be done by overriding res.send

We override the res.send function to capture the response body in our API analytics tool as follows

// It will monkey patch the res.send.
// The patch intercepts the send invocation, executes is logic such as atatus.setResponseBody
// then restores the original send function and invokes that to finalize the req/res chain
const resSendInterceptor = (res, send) => (content) => {

    // Set response body in Atatus Analytics
    // Atatus is our API analytics tool
    atatus.setResponseBody(content || '');

    // TODO: You can modify your response body as you wish.

    // Invoke the original send function.
    res.send = send;
    send.apply(this, arguments);

};

// Express Middleware
app.use((req, res, next) => {

    // Overrides res.send
    res.send = resSendInterceptor(res, res.send);
    
    return next();
});

Upvotes: 0

slava
slava

Reputation: 524

One more solution from here:

expressApp.use(function (req, res, next) {
    req.on("end", function () {
        console.log('on request end');
    });
    next();
});

Important Note: To work, this needs to be placed before body parser since it recreates the response object. see this answer

Upvotes: 6

Farid Nouri Neshat
Farid Nouri Neshat

Reputation: 30430

Well you can override the send function:

app.use(function (req, res) {
    var send = res.send;
    res.send = function (body) { // It might be a little tricky here, because send supports a variety of arguments, and you have to make sure you support all of them!
        // Do something with the body...
        send.call(this, body);
    };
});

If you want to support more than just calling send(like calling end method), then you have to override more functions...

You can check connect-livereload on how it adds a script to any html output.

Upvotes: 37

Datsik
Datsik

Reputation: 14824

Your lack of code makes it really hard to answer your question, but you could use something like

Express 4.0:
router.use('/path', function (req, res) {
    // Modify req
});

.use on a route will parse that before continuing on to the actual route so if somebody submitted a form or something, it will hit the .use before it goes to the .post or .get

Or you can do

Express 4.0:
app.use(function (req, res) {
    // Modify Req
    if (req.body.hasOwnProperty('some_form_name')) {
       // Do Somthing
    }
});

Which is the same thing, but it will be called before every request for every route.

Not sure if this answers your question but I think this might be what you're looking for?

Upvotes: -7

Related Questions