24

Here's the basic setup. I'm trying to create a simple middleware component that would allow me to easily pass data from my route directly to my javascript in the client side. (Very similiar to the Gon gem in ruby). The way I'm doing it is by having a module that looks like this:

    module.exports = function(){
    return function(req,res,next){
        var app = req.app;
        if(typeof(app) == 'undefined'){
            var err = new Error("The JShare module requires express");
            next(err);
            return;
        }
        res.jshare = {};
        app.dynamicHelpers({
            includeJShare: function(req,res){
                if(typeof(res.jshare) === 'undefined'){
                    return "";
                }
                return function(){
                    return '<script type="text/javascript">window.jshare=' + JSON.stringify(res.jshare) + '</script>';
                } 
            }
        });
        next();
    };
}

Then, in my route I can do this:

exports.index = function(req, res){
  res.jshare.person = {firstName : "Alex"};
  res.render('index', { title: 'Express' })
};

Finally in the layout.jade:

!{includeJShare()}

What that does is in outputs a line of javascript on the client that creates the exact JSON object that was created server side.

Here's the question; it all works as expected, but being new to Express and Node.js in general, I was just curious if attaching properties onto the response object is OK, or is there something wrong with doing it that I'm simply overlooking? For some reason it doesn't pass my "smell test" but I'm not sure why.....

BFree
  • 102,548
  • 21
  • 159
  • 201

3 Answers3

43

I know this is an old thread, but there is something else to add to this topic.

Express has a response.locals object which is meant for this purpose - extending the response from middleware to make it available to views.

You could add a property directly to the response object, and as @hasanyasin indicated, is how JavaScript is designed. But Express, more specifically, has a particular way they prefer we do it.

This may be new in express 3.x, not sure. Perhaps it didn't exist when this question was asked.

For details, see

http://expressjs.com/en/api.html#res.locals

There is also an app.locals for objects which don't vary from request to request (or response to response I suppose).

http://expressjs.com/en/api.html#app.locals

See also: req.locals vs. res.locals vs. res.data vs. req.data vs. app.locals in Express middleware

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Brandon
  • 9,822
  • 3
  • 27
  • 37
  • dude, your link is broken and i can't find any reference of this? – Himmators Feb 16 '16 at 22:20
  • 2
    The Express team changed their web site URL pattern to include a locale code. I've updated the links in this answer to use "en", which works correctly. – Brandon Feb 17 '16 at 01:55
  • This is a better answer, @Bfree, you should change it! – Himmators Feb 19 '16 at 18:05
  • 3
    Seems to me like the pattern here ought to be "things relevant to the request, to be handed off to later middleware get appended to `req`, while things destined to be formatted/sent back with the response belong in `res.locals`. – woodardj Jun 28 '17 at 18:23
16

It is perfectly OK. It is how JavaScript is designed. Only thing you should be careful is to not accidentally overriding already existing properties or being overridden by others. To be safer, instead of adding everything directly to req/res objects, you might consider going a level deeper:

res.mydata={}
res.mydata.person= ...

Like that.

hasanyasin
  • 6,222
  • 1
  • 17
  • 16
  • Thanks for your response. If you look at my code sample, I believe I am going one level deeper, I have "res.jshare.person". Is that what you meant? – BFree Jul 05 '12 at 04:34
  • Yes, that is exactly what I meant. I did not mean to criticize your code, I just wanted to emphasize it. So you did it correct already and jshare does not look like a generic word that would end up being used by another library. It is good. :) – hasanyasin Jul 05 '12 at 04:49
  • I can't think of a reason not too, but I've more commonly seen things added to the request. Node and Connect/Express's power comes from passing these objects around, and each layer extends them in it's own way. Express adds send() to the response object, for instance. – Timothy Meade Jul 05 '12 at 07:19
  • 2
    Would [res.locals](http://expressjs.com/4x/api.html#res.locals) be a logical place to store these kinds of data? – algoni Apr 02 '15 at 11:40
  • 2
    Just because JS permits this sort of thing doesn't mean you should. Never add random properties to a library object like this. What if some future version of Express begins using the `res.mydata` property? Unlikely in that example, but that's just `mydata` -- your property might not be so contrived. You'll have a broken app after upgrading. Best case scenario, it's confusing from a readability standpoint -- which keys did I make up and which are library functions? Use [`res.locals`](http://expressjs.com/en/4x/api.html), the object Express explicitly provides for this purpose, as mentioned. – ggorlen Jul 27 '21 at 18:03
  • Not to question the motivation behind commenting on a 9-year old post, but I must remind the readers arriving here that, back then, Express 3 was in early alpha and Express 2 did NOT have `res.locals`. Plus, JS was also quite a different language and JS objects, specifically Express 2 req/res objects were indeed designed to be used this way. Finally, if migrating an app one coded in 2012 to the latest version of the framework today would just work if not for a name clash, that would be so awesome. :D – hasanyasin Jul 29 '21 at 12:39
-2

Use res.locals for including custom variables in your response object.

JoeTidee
  • 24,754
  • 25
  • 104
  • 149
  • How does this add anything to [this answer](https://stackoverflow.com/a/15371581/6243352)? 7 years later with far less information and resources provided. – ggorlen Jul 27 '21 at 18:06