Re: how does app.locals work?

6,618 views
Skip to first unread message

tjholowaychuk

unread,
Mar 10, 2013, 4:15:28 PM3/10/13
to Express
You would use res.locals in a middleware, if you need to persist
something in a "global" fashion then
you would combine res.locals and req.session or the database

On Mar 7, 8:03 pm, Jason Gelinas <jjgeli...@gmail.com> wrote:
> Just getting started with express.js.
>
> Is app.locals global for all users/sessions hitting the server?  I ran a
> test and that seems to be the case.
>
> I would like to have a global variable (a json array) that can be used by
> all the views, but is unique for each user/session.
>
> What's the best way to implement this? I know about res.locals, but that
> only works for single request/view.  I need the global variable to be
> available to multiple views.
>
> Thanks

greelgorke

unread,
Mar 11, 2013, 4:57:59 AM3/11/13
to expre...@googlegroups.com
unique data pre user/sessions, as TJ said, this is what is req.session for. req.locals is exactly the same as req.session, but only selfmade. this is why you've never seen someone doing it, because req.session is there.

to your question: you create 2 separate applications with separated app.locals, and then you mount the app in route.js into your main app. 

you have different options to solve that. first one is not to mount separate app:

./app.js
    var express = require('express');
    var app = express();

    app.locals.foo = 'some things';  // i want to globalize foo.

    var route = require('./lib.route');
    route(app);


./lib/route.js
module.exports = function(app){
    app.get('/route', function (req, res, next) {
      
      assert.equal(app.locals.foo, 'some things'); // this will throw

    })
}

this way you have one app with several routes

another option is to pass your "global" to ever single mounted app:

./app.js
    var express = require('express');
    var app = express();

    app.locals.foo = 'some things';  // i want to globalize foo.

    var route = require('./lib.route');
    app.use(route);
    route.locals = app.locals


./lib/route.js
    var express = require('express');
    var app = module.exports = express();

    app.get('/route', function (req, res, next) {
      
      assert.equal(app.locals.foo, 'some things'); // this will throw

    })

another option is to put your locals into a separate file and require it then:

./locals.js
module.exports = {
  foo : "some things"
}

./app.js
    var express = require('express');
    var app = express();

    app.locals = require('./locals.js')

    var route = require('./lib.route');
    app.use(route);


./lib/route.js
    var express = require('express');
    var app = module.exports = express();
    app.locals = require('./locals.js')
    app.get('/route', function (req, res, next) {
      
      assert.equal(app.locals.foo, 'some things'); // this will throw

    })
because node caches the require calls every app gets the same locals hash.

there are surely more options to solve that :)
 
Am Sonntag, 10. März 2013 21:53:04 UTC+1 schrieb Stephen Bartell:
I was going to ask the same question.

First @Jason:
I made some middleware that, per req, will do some auth things.  So I wanted the results of the auth middleware to be available for the rest of the handler stack. At the top of my handler stack, i create a `req.locals`, like app.locals and res.locals.  Then middleware will hang things off of it.

For example: 

    app.use(function (req, res, next){
      req.locals  = {};
      next()
    })
    app.use(authMiddleware);
    app.use(x)
    app.use(y)

Then authMiddleware will add things to req.locals for the rest of the handlers to use.  I dont use any views since I make mostly web services.  But res.locals is for that.  So you would assign req.locals to res.locals and be on your way.  

I havent seen anyone else doing this (req.locals), so to me it smells a little.  But I think it makes sense since per-user things belong in the context of the request.  It wouldnt really make sense to make it available globally via app.locals. If this is a bad idea could someone speak up?


Now about app.locals. My question is about app.locals when my handlers are more modular and spread accross mutliple files: ie:

./app.js
    var express = require('express');
    var app = express();

    app.locals.foo = 'some things';  // i want to globalize foo.

    var route = require('./lib.route');
    app.use(route);


./lib/route.js
    var express = require('express');
    var app = module.exports = express();

    app.get('/route', function (req, res, next) {
      
      assert.equal(app.locals.foo, 'some things'); // this will throw

    })


For the life of me I cant get foo inside of my other handlers (route.js)

Could someone help me see what Im doing wrong here?

Jason J Gelinas

unread,
Mar 11, 2013, 1:35:25 PM3/11/13
to expre...@googlegroups.com
req.session is exactly what I was looking for.  Thanks!

--
You received this message because you are subscribed to the Google Groups "Express" group.
To unsubscribe from this group and stop receiving emails from it, send an email to express-js+...@googlegroups.com.
To post to this group, send email to expre...@googlegroups.com.
Visit this group at http://groups.google.com/group/express-js?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.



Ryan Schmidt

unread,
Mar 11, 2013, 4:58:31 PM3/11/13
to expre...@googlegroups.com

On Mar 7, 2013, at 21:03, Jason Gelinas <jjge...@gmail.com> wrote:

> Is app.locals global for all users/sessions hitting the server? I ran a test and that seems to be the case.

Yes.


> I would like to have a global variable (a json array) that can be used by all the views, but is unique for each user/session.
>
> What's the best way to implement this? I know about res.locals, but that only works for single request/view. I need the global variable to be available to multiple views.

It sounds like you want to use Express's cookie session. You can then either make req.session available to the view (by putting it into res.locals), or just take specific items from the session and put them in res.locals.
Reply all
Reply to author
Forward
0 new messages