Node.js / Express.js - How to override/intercept res.render function?
Old question, but found myself asking the same thing. How to intercept res render?Using express 4.0x something now.
You can use/write middleware. The concept was a bit daunting to me at first, but after some reading it made a little more sense. And just for some context for anyone else reading this, the motivation for overriding res.render was to provide global view variables. I want session
to be available in all my templates without me having to type it in every res object.
The basic middleware format is.
app.use( function( req, res, next ) { //.... next();} );
The next param and function call are crucial to execution. next
is the callback function, to allow multiple middleware to do their thing without blocking. For a better explanation read here
This can then be used to override render logic
app.use( function( req, res, next ) { // grab reference of render var _render = res.render; // override logic res.render = function( view, options, fn ) { // do some custom logic _.extend( options, {session: true} ); // continue with original render _render.call( this, view, options, fn ); } next();} );
I've tested this code, using express 3.0.6. It should work with 4.x without issue.You can also override specific URLs combos with
app.use( '/myspcificurl', function( req, res, next ) {...} );
It's not a good idea to use a middleware to override a response or request method for each instance of them because the middleware is get executed for each and every request and each time it get called you use cpu as well as memory because you are creating a new function.
As you may know javascript is a Prototype-based language and every object has a prototype, like response and request objects. By looking at code (express 4.13.4) you can find their prototypes:
req => express.requestres => express.response
So when you want to override a method for every single instance of a response it's much much better to override it in it's prototype as it's done once is available in every instance of response:
var app = (global.express = require('express'))();var render = express.response.render;express.response.render = function(view, options, callback) { // desired code /** here this refer to the current res instance and you can even access req for this res: **/ console.log(this.req); render.apply(this, arguments);};
The response
object doesn't have a prototype. This should work (taking Ryan's idea of putting it in a middleware):
var wrapRender = function(req, res, next) { var _render = res.render; res.render = function(view, options, callback) { _render.call(res, "testViews/" + view, options, callback); };};
However, it might be better to hack the ServerResponse.prototype:
var express = require("express") , http = require("http") , response = http.ServerResponse.prototype , _render = response.render;response.render = function(view, options, callback) { _render.call(this, "testViews/" + view, options, callback);};