diff --git a/lib/context.js b/lib/context.js index c4622a1..1b30f76 100644 --- a/lib/context.js +++ b/lib/context.js @@ -113,7 +113,7 @@ class ContextSession { } catch (err) { // backwards compatibility: // create a new session if parsing fails. - // new Buffer(string, 'base64') does not seem to crash + // Buffer.alloc(size, string, 'base64') does not seem to crash // when `string` is not base64-encoded. // but `JSON.parse(string)` will crash. debug('decode %j error: %s', cookie, err); diff --git a/lib/session.js b/lib/session.js index b585f2a..07a439b 100644 --- a/lib/session.js +++ b/lib/session.js @@ -55,7 +55,7 @@ class Session { } /** - * Return how many values there are in the session object. + * Return how many keys there are in the session object. * Used to see if it's "populated". * * @return {Number} diff --git a/lib/util.js b/lib/util.js index 2bdd7b8..30ecdc6 100644 --- a/lib/util.js +++ b/lib/util.js @@ -13,7 +13,7 @@ module.exports = { */ decode(string) { - const body = new Buffer(string, 'base64').toString('utf8'); + const body = Buffer.alloc(Buffer.byteLength(string, 'base64'), string, 'base64').toString('utf8'); const json = JSON.parse(body); return json; }, @@ -28,7 +28,7 @@ module.exports = { encode(body) { body = JSON.stringify(body); - return new Buffer(body).toString('base64'); + return Buffer.alloc(Buffer.byteLength(body), body).toString('base64'); }, hash(sess) { diff --git a/package.json b/package.json index d12da0b..4ab9d35 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "license": "MIT", "dependencies": { "crc": "^3.4.4", - "debug": "^2.2.0", + "debug": "^2.6.9", "is-type-of": "^1.0.0", "uid-safe": "^2.1.3" }, diff --git a/test/cookie.test.js b/test/cookie.test.js index dc15fb9..9b24f19 100644 --- a/test/cookie.test.js +++ b/test/cookie.test.js @@ -348,7 +348,7 @@ describe('Koa Session Cookie', () => { }); describe('.length', () => { - it('should return session length', done => { + it('should return session`s keys length', done => { const app = App(); app.use(async function(ctx) { @@ -464,6 +464,35 @@ describe('Koa Session Cookie', () => { .expect(500, done); }); }); + + describe('contains multibyte character', () => { + it('should still work', done => { + const app = App(); + const MULTIBYTE_CHAR = '€'; + + app.use(async function(ctx) { + if (ctx.method === 'POST') { + ctx.session.string = MULTIBYTE_CHAR; + ctx.status = 204; + } else { + ctx.body = ctx.session.string; + } + }); + + const server = app.listen(); + + request(server) + .post('/') + .expect(204, (err, res) => { + if (err) return done(err); + const cookie = res.headers['set-cookie']; + request(server) + .get('/') + .set('Cookie', cookie.join(';')) + .expect(MULTIBYTE_CHAR, done); + }); + }); + }); }); describe('when an error is thrown downstream and caught upstream', () => {