@@ -74,6 +74,7 @@ var defer = typeof setImmediate === 'function'
7474 * @param {Function } [options.genid]
7575 * @param {String } [options.name=connect.sid] Session ID cookie name
7676 * @param {Boolean } [options.proxy]
77+ * @param {Boolean } [options.propagateTouch] Whether session.touch() should call store.touch()
7778 * @param {Boolean } [options.resave] Resave unmodified sessions back to the store
7879 * @param {Boolean } [options.rolling] Enable/disable rolling session expiration
7980 * @param {Boolean } [options.saveUninitialized] Save uninitialized sessions to the store
@@ -96,6 +97,11 @@ function session(options) {
9697 // get the session cookie name
9798 var name = opts . name || opts . key || 'connect.sid'
9899
100+ var propagateTouch = opts . propagateTouch ;
101+ if ( ! propagateTouch ) {
102+ deprecate ( 'falsy propagateTouch option; set to true' ) ;
103+ }
104+
99105 // get the session store
100106 var store = opts . store || new MemoryStore ( )
101107
@@ -209,6 +215,19 @@ function session(options) {
209215 var originalId ;
210216 var savedHash ;
211217 var touched = false
218+ var touchedStore = false ;
219+
220+ function autoTouch ( ) {
221+ if ( touched ) return ;
222+ // For legacy reasons, auto-touch does not touch the session in the store. That is done later.
223+ var backup = propagateTouch ;
224+ propagateTouch = false ;
225+ try {
226+ req . session . touch ( ) ;
227+ } finally {
228+ propagateTouch = backup ;
229+ }
230+ }
212231
213232 // expose store
214233 req . sessionStore = store ;
@@ -233,11 +252,7 @@ function session(options) {
233252 return ;
234253 }
235254
236- if ( ! touched ) {
237- // touch session
238- req . session . touch ( )
239- touched = true
240- }
255+ autoTouch ( ) ;
241256
242257 // set cookie
243258 setcookie ( res , name , req . sessionID , secrets [ 0 ] , req . session . cookie . data ) ;
@@ -325,11 +340,7 @@ function session(options) {
325340 return _end . call ( res , chunk , encoding ) ;
326341 }
327342
328- if ( ! touched ) {
329- // touch session
330- req . session . touch ( )
331- touched = true
332- }
343+ autoTouch ( ) ;
333344
334345 if ( shouldSave ( req ) ) {
335346 req . session . save ( function onsave ( err ) {
@@ -394,6 +405,7 @@ function session(options) {
394405 function wrapmethods ( sess ) {
395406 var _reload = sess . reload
396407 var _save = sess . save ;
408+ var _touch = sess . touch ;
397409
398410 function reload ( callback ) {
399411 debug ( 'reloading %s' , this . id )
@@ -406,6 +418,21 @@ function session(options) {
406418 _save . apply ( this , arguments ) ;
407419 }
408420
421+ function touch ( callback ) {
422+ debug ( 'touching %s' , this . id ) ;
423+ var cb = callback || function ( err ) { if ( err ) throw err ; } ;
424+ var touchStore = propagateTouch && storeImplementsTouch &&
425+ // Don't touch the store unless the session has been or will be written to the store.
426+ ( saveUninitializedSession || isModified ( this ) || isSaved ( this ) ) ;
427+ _touch . call ( this , touchStore ? ( function ( err ) {
428+ if ( err ) return cb ( err ) ;
429+ store . touch ( this . id , this , cb ) ;
430+ touchedStore = true ; // Set synchronously regardless of success/failure.
431+ } ) . bind ( this ) : cb ) ;
432+ touched = true ; // Set synchronously regardless of success/failure.
433+ return this ;
434+ }
435+
409436 Object . defineProperty ( sess , 'reload' , {
410437 configurable : true ,
411438 enumerable : false ,
@@ -419,6 +446,13 @@ function session(options) {
419446 value : save ,
420447 writable : true
421448 } ) ;
449+
450+ Object . defineProperty ( sess , 'touch' , {
451+ configurable : true ,
452+ enumerable : false ,
453+ value : touch ,
454+ writable : true
455+ } ) ;
422456 }
423457
424458 // check if session has been modified
@@ -457,7 +491,7 @@ function session(options) {
457491 return false ;
458492 }
459493
460- return cookieId === req . sessionID && ! shouldSave ( req ) ;
494+ return ! touchedStore && cookieId === req . sessionID && ! shouldSave ( req ) ;
461495 }
462496
463497 // determine if cookie should be set on response
0 commit comments