description and source-codefunction cookieSession(options) {
var opts = options || {}
// name - previously "opts.key"
var name = opts.name || opts.key || 'express:sess';
// secrets
var keys = opts.keys;
if (!keys && opts.secret) keys = [opts.secret];
// defaults
if (null == opts.overwrite) opts.overwrite = true;
if (null == opts.httpOnly) opts.httpOnly = true;
if (null == opts.signed) opts.signed = true;
if (!keys && opts.signed) throw new Error('.keys required.');
debug('session options %j', opts);
return function _cookieSession(req, res, next) {
var cookies = req.sessionCookies = new Cookies(req, res, keys);
var sess, json;
// to pass to Session()
req.sessionOptions = Object.create(opts)
req.sessionKey = name
req.__defineGetter__('session', function(){
// already retrieved
if (sess) return sess;
// unset
if (false === sess) return null;
json = cookies.get(name, req.sessionOptions)
if (json) {
debug('parse %s', json);
try {
sess = new Session(req, decode(json));
} catch (err) {
// backwards compatibility:
// create a new session if parsing fails.
// new Buffer(string, 'base64') does not seem to crash
// when `string` is not base64-encoded.
// but `JSON.parse(string)` will crash.
if (!(err instanceof SyntaxError)) throw err;
sess = new Session(req);
}
} else {
debug('new session');
sess = new Session(req);
}
return sess;
});
req.__defineSetter__('session', function(val){
if (null == val) return sess = false;
if ('object' == typeof val) return sess = new Session(req, val);
throw new Error('req.session can only be set as null or an object.');
});
onHeaders(res, function setHeaders() {
if (sess === undefined) {
// not accessed
return;
}
try {
if (sess === false) {
// remove
cookies.set(name, '', req.sessionOptions)
} else if (!json && !sess.length) {
// do nothing if new and not populated
} else if (sess.changed(json)) {
// save
sess.save();
}
} catch (e) {
debug('error saving session %s', e.message);
}
});
next();
}
}