Skip to content

Commit ee1fd18

Browse files
authored
fix(index): touch() or set() should update cookie expiration (#265)
* fix(index): touch() or set() should update cookie expiration * test: minor fix Signed-off-by: Andrei Alecu <[email protected]> --------- Signed-off-by: Andrei Alecu <[email protected]> Co-authored-by: Andrei Alecu <[email protected]>
1 parent c0f609f commit ee1fd18

File tree

2 files changed

+92
-3
lines changed

2 files changed

+92
-3
lines changed

index.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -317,13 +317,13 @@ class Session {
317317
}
318318

319319
set (key, value) {
320-
this.changed = true
320+
this.touch()
321321
this[kObj][key] = value
322322
}
323323

324324
delete () {
325-
this.changed = true
326325
this.deleted = true
326+
this.touch()
327327
}
328328

329329
options (opts) {
@@ -341,6 +341,7 @@ class Session {
341341

342342
touch () {
343343
this.changed = true
344+
this[kObj].__ts = Math.round(Date.now() / 1000)
344345
}
345346

346347
regenerate (ignoredFields) {
@@ -350,7 +351,7 @@ class Session {
350351
}
351352
delete this[kObj][key]
352353
}
353-
this.changed = true
354+
this.touch()
354355
}
355356
}
356357

test/anti-reuse.test.js

+88
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,91 @@ test('Anti re-use with set expiry of 15 minutes', async t => {
115115
t.assert.ok(getResponse)
116116
t.assert.deepStrictEqual(JSON.parse(getResponse.payload), {})
117117
})
118+
119+
test('Anti re-use should still allow touch() to work', async t => {
120+
const fastify = Fastify({ logger: false })
121+
const clock = FakeTimers.install({
122+
shouldAdvanceTime: true,
123+
now: Date.now()
124+
})
125+
t.after(() => {
126+
fastify.close()
127+
clock.reset()
128+
clock.uninstall()
129+
})
130+
131+
fastify.register(require('../'), {
132+
key,
133+
expiry: 15 * 60 // 15 minutes
134+
})
135+
136+
fastify.post('/', (request, reply) => {
137+
request.session.set('some', request.body.some)
138+
request.session.set('some2', request.body.some2)
139+
request.session.touch()
140+
reply.send('hello world')
141+
})
142+
143+
fastify.get('/', (request, reply) => {
144+
const some = request.session.get('some')
145+
const some2 = request.session.get('some2')
146+
reply.send({ some, some2 })
147+
})
148+
149+
const payload = {
150+
some: 'someData',
151+
some2: { a: 1, b: 2, c: 3 }
152+
}
153+
154+
const firstPostResponse = await fastify.inject({
155+
method: 'POST',
156+
url: '/',
157+
payload
158+
})
159+
const oldCookie = firstPostResponse.headers['set-cookie']
160+
161+
t.assert.ok(firstPostResponse)
162+
t.assert.strictEqual(firstPostResponse.statusCode, 200)
163+
t.assert.ok(firstPostResponse.headers['set-cookie'])
164+
165+
clock.jump('00:14:59') // forward just before expiry
166+
167+
const secondPostResponse = await fastify.inject({
168+
method: 'POST',
169+
url: '/',
170+
payload
171+
})
172+
const newCookie = secondPostResponse.headers['set-cookie']
173+
174+
t.assert.ok(secondPostResponse)
175+
t.assert.strictEqual(secondPostResponse.statusCode, 200)
176+
t.assert.ok(secondPostResponse.headers['set-cookie'])
177+
178+
clock.jump('00:00:02') // forward just after expiry
179+
180+
const withNewCookie = await fastify.inject({
181+
method: 'GET',
182+
url: '/',
183+
headers: {
184+
cookie: newCookie
185+
}
186+
})
187+
188+
t.assert.ok(withNewCookie)
189+
190+
// this should return the payload because the cookie was updated 2 seconds before
191+
t.assert.deepStrictEqual(JSON.parse(withNewCookie.payload), payload)
192+
193+
const withOldCookie = await fastify.inject({
194+
method: 'GET',
195+
url: '/',
196+
headers: {
197+
cookie: oldCookie
198+
}
199+
})
200+
201+
t.assert.ok(withOldCookie)
202+
203+
// this should be empty because the old session is expired
204+
t.assert.deepStrictEqual(JSON.parse(withOldCookie.payload), {})
205+
})

0 commit comments

Comments
 (0)