@@ -157,11 +157,7 @@ function session(options) {
157
157
store . generate = function ( req ) {
158
158
req . sessionID = generateId ( req ) ;
159
159
req . session = new Session ( req ) ;
160
- req . session . cookie = new Cookie ( cookieOptions ) ;
161
-
162
- if ( cookieOptions . secure === 'auto' ) {
163
- req . session . cookie . secure = issecure ( req , trustProxy ) ;
164
- }
160
+ req . session . cookie = createCookie ( cookieOptions , req , trustProxy ) ;
165
161
} ;
166
162
167
163
var storeImplementsTouch = typeof store . touch === 'function' ;
@@ -217,29 +213,47 @@ function session(options) {
217
213
218
214
// set-cookie
219
215
onHeaders ( res , function ( ) {
216
+
217
+ // Is this an existing session that is being destroyed?
218
+ var isDestroying = isBeingDestroyed ( req ) ;
219
+
220
220
if ( ! req . session ) {
221
221
debug ( 'no session' ) ;
222
- return ;
222
+ if ( ! isDestroying || isInitialSession ( req ) ) {
223
+ return ;
224
+ }
223
225
}
224
226
225
- if ( ! shouldSetCookie ( req ) ) {
226
- return ;
227
+ var cookie = req . session ? req . session . cookie : undefined ;
228
+ if ( isDestroying ) {
229
+ if ( cookie == null ) {
230
+ debug ( 'creating expired cookie' ) ;
231
+ cookie = createCookie ( cookieOptions , req , trustProxy ) ;
232
+ }
233
+
234
+ // Set the cookie to immediately expire on the client
235
+ cookie . maxAge = 0 ;
227
236
}
228
237
229
238
// only send secure cookies via https
230
- if ( req . session . cookie . secure && ! issecure ( req , trustProxy ) ) {
239
+ if ( cookie . secure && ! issecure ( req , trustProxy ) ) {
231
240
debug ( 'not secured' ) ;
232
241
return ;
233
242
}
234
243
235
- if ( ! touched ) {
236
- // touch session
237
- req . session . touch ( )
238
- touched = true
244
+ if ( ! isDestroying ) {
245
+ if ( ! shouldSetCookie ( req ) ) {
246
+ return ;
247
+ }
248
+ else if ( ! touched ) {
249
+ // touch session
250
+ req . session . touch ( ) ;
251
+ touched = true ;
252
+ }
239
253
}
240
254
241
255
// set cookie
242
- setcookie ( res , name , req . sessionID , secrets [ 0 ] , req . session . cookie . data ) ;
256
+ setcookie ( res , name , req . sessionID , secrets [ 0 ] , cookie . data ) ;
243
257
} ) ;
244
258
245
259
// proxy end() to commit the session
@@ -396,6 +410,16 @@ function session(options) {
396
410
} ) ;
397
411
}
398
412
413
+ // check if session has been or is being destroyed
414
+ function isBeingDestroyed ( req ) {
415
+ return req . sessionID && req . session == null ;
416
+ }
417
+
418
+ // check if session is the initial session
419
+ function isInitialSession ( req ) {
420
+ return req . sessionID && cookieId != req . sessionID ;
421
+ }
422
+
399
423
// check if session has been modified
400
424
function isModified ( sess ) {
401
425
return originalId !== sess . id || originalHash !== hash ( sess ) ;
@@ -437,8 +461,8 @@ function session(options) {
437
461
438
462
// determine if cookie should be set on response
439
463
function shouldSetCookie ( req ) {
440
- // cannot set cookie without a session ID
441
- if ( typeof req . sessionID !== 'string' ) {
464
+ // cannot set cookie without a session ID and a session
465
+ if ( typeof req . sessionID !== 'string' || ! req . session ) {
442
466
return false ;
443
467
}
444
468
@@ -491,6 +515,25 @@ function session(options) {
491
515
} ;
492
516
} ;
493
517
518
+ /**
519
+ * Create a new Cookie for this request.
520
+ *
521
+ * @param {Object } cookieOptions
522
+ * @param {Object } req
523
+ * @param {Boolean } [trustProxy]
524
+ * @return {Cookie }
525
+ * @private
526
+ */
527
+ function createCookie ( cookieOptions , req , trustProxy ) {
528
+ var cookieOpts = cookieOptions || { } ;
529
+
530
+ var cookie = new Cookie ( cookieOpts ) ;
531
+ if ( cookieOpts . secure === 'auto' ) {
532
+ cookie . secure = issecure ( req , trustProxy ) ;
533
+ }
534
+ return cookie ;
535
+ }
536
+
494
537
/**
495
538
* Generate a session ID for a new session.
496
539
*
0 commit comments