@@ -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
@@ -380,6 +394,16 @@ function session(options) {
380
394
} ) ;
381
395
}
382
396
397
+ // check if session has been or is being destroyed
398
+ function isBeingDestroyed ( req ) {
399
+ return req . sessionID && req . session == null ;
400
+ }
401
+
402
+ // check if session is the initial session
403
+ function isInitialSession ( req ) {
404
+ return req . sessionID && cookieId != req . sessionID ;
405
+ }
406
+
383
407
// check if session has been modified
384
408
function isModified ( sess ) {
385
409
return originalId !== sess . id || originalHash !== hash ( sess ) ;
@@ -421,8 +445,8 @@ function session(options) {
421
445
422
446
// determine if cookie should be set on response
423
447
function shouldSetCookie ( req ) {
424
- // cannot set cookie without a session ID
425
- if ( typeof req . sessionID !== 'string' ) {
448
+ // cannot set cookie without a session ID and a session
449
+ if ( typeof req . sessionID !== 'string' || ! req . session ) {
426
450
return false ;
427
451
}
428
452
@@ -475,6 +499,25 @@ function session(options) {
475
499
} ;
476
500
} ;
477
501
502
+ /**
503
+ * Create a new Cookie for this request.
504
+ *
505
+ * @param {Object } cookieOptions
506
+ * @param {Object } req
507
+ * @param {Boolean } [trustProxy]
508
+ * @return {Cookie }
509
+ * @private
510
+ */
511
+ function createCookie ( cookieOptions , req , trustProxy ) {
512
+ var cookieOpts = cookieOptions || { } ;
513
+
514
+ var cookie = new Cookie ( cookieOpts ) ;
515
+ if ( cookieOpts . secure === 'auto' ) {
516
+ cookie . secure = issecure ( req , trustProxy ) ;
517
+ }
518
+ return cookie ;
519
+ }
520
+
478
521
/**
479
522
* Generate a session ID for a new session.
480
523
*
0 commit comments