arnaucube
arnaucube/raspberryGPIOhtmlserverPublic Self-hosted repository
raspberryGPIOhtmlserver/node_modules/connect/lib/middleware/cookieSession.js
node_modules/connect/lib/middleware/cookieSession.jsRaw
  1
  2/*!
  3 * Connect - cookieSession
  4 * Copyright(c) 2011 Sencha Inc.
  5 * MIT Licensed
  6 */
  7
  8/**
  9 * Module dependencies.
 10 */
 11
 12var utils = require('./../utils')
 13  , Cookie = require('./session/cookie')
 14  , debug = require('debug')('connect:cookieSession')
 15  , signature = require('cookie-signature')
 16  , crc32 = require('buffer-crc32');
 17
 18/**
 19 * Cookie Session:
 20 *
 21 *   Cookie session middleware.
 22 *
 23 *      var app = connect();
 24 *      app.use(connect.cookieParser());
 25 *      app.use(connect.cookieSession({ secret: 'tobo!', cookie: { maxAge: 60 * 60 * 1000 }}));
 26 *
 27 * Options:
 28 *
 29 *   - `key` cookie name defaulting to `connect.sess`
 30 *   - `secret` prevents cookie tampering
 31 *   - `cookie` session cookie settings, defaulting to `{ path: '/', httpOnly: true, maxAge: null }`
 32 *   - `proxy` trust the reverse proxy when setting secure cookies (via "x-forwarded-proto")
 33 *
 34 * Clearing sessions:
 35 *
 36 *  To clear the session simply set its value to `null`,
 37 *  `cookieSession()` will then respond with a 1970 Set-Cookie.
 38 *
 39 *     req.session = null;
 40 *
 41 * @param {Object} options
 42 * @return {Function}
 43 * @api public
 44 */
 45
 46module.exports = function cookieSession(options){
 47  // TODO: utilize Session/Cookie to unify API
 48  options = options || {};
 49  var key = options.key || 'connect.sess'
 50    , trustProxy = options.proxy;
 51
 52  return function cookieSession(req, res, next) {
 53
 54    // req.secret is for backwards compatibility
 55    var secret = options.secret || req.secret;
 56    if (!secret) throw new Error('`secret` option required for cookie sessions');
 57
 58    // default session
 59    req.session = {};
 60    var cookie = req.session.cookie = new Cookie(options.cookie);
 61
 62    // pathname mismatch
 63    if (0 != req.originalUrl.indexOf(cookie.path)) return next();
 64
 65    // cookieParser secret
 66    if (!options.secret && req.secret) {
 67      req.session = req.signedCookies[key] || {};
 68      req.session.cookie = cookie;
 69    } else {
 70      // TODO: refactor
 71      var rawCookie = req.cookies[key];
 72      if (rawCookie) {
 73        var unsigned = utils.parseSignedCookie(rawCookie, secret);
 74        if (unsigned) {
 75          var originalHash = crc32.signed(unsigned);
 76          req.session = utils.parseJSONCookie(unsigned) || {};
 77          req.session.cookie = cookie;
 78        }
 79      }
 80    }
 81
 82    res.on('header', function(){
 83      // removed
 84      if (!req.session) {
 85        debug('clear session');
 86        cookie.expires = new Date(0);
 87        res.setHeader('Set-Cookie', cookie.serialize(key, ''));
 88        return;
 89      }
 90
 91      delete req.session.cookie;
 92
 93      // check security
 94      var proto = (req.headers['x-forwarded-proto'] || '').toLowerCase()
 95        , tls = req.connection.encrypted || (trustProxy && 'https' == proto)
 96        , secured = cookie.secure && tls;
 97
 98      // only send secure cookies via https
 99      if (cookie.secure && !secured) return debug('not secured');
100
101      // serialize
102      debug('serializing %j', req.session);
103      var val = 'j:' + JSON.stringify(req.session);
104
105      // compare hashes, no need to set-cookie if unchanged
106      if (originalHash == crc32.signed(val)) return debug('unmodified session');
107
108      // set-cookie
109      val = 's:' + signature.sign(val, secret);
110      val = cookie.serialize(key, val);
111      debug('set-cookie %j', cookie);
112      res.setHeader('Set-Cookie', val);
113    });
114
115    next();
116  };
117};