Skip to content

Commit 7743e46

Browse files
provide option to configure HttpOnly cookie (#89)
1 parent 5eef654 commit 7743e46

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ As with all modules you can either pass the constructor function (class) to the
403403
cookiePath: '/my/path',
404404
cookieSecure: true, // if need secure cookie
405405
cookieSameSite: 'strict', // 'strict', 'lax' or 'none'
406+
cookieHttpOnly: true // prevent client-side script access to the cookie
406407

407408
// optional conversion function used to modify the detected language code
408409
convertDetectedLanguage: 'Iso15897',

lib/languageLookups/cookie.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export default {
7979
expires: expirationDate,
8080
domain: options.cookieDomain,
8181
path: options.cookiePath,
82-
httpOnly: false,
82+
httpOnly: options.cookieHttpOnly ?? false,
8383
overwrite: true,
8484
sameSite: options.cookieSameSite
8585
}

test/languageDetector.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,60 @@ describe('language detector', () => {
4848
expect(res.headers['Set-Cookie']).to.match(/my=cookie/)
4949
expect(res.headers['Set-Cookie']).to.match(/SameSite=None/)
5050
})
51+
52+
it('does not set httpOnly flag by default', () => {
53+
const ld = new LanguageDetector(i18next.services, { order: ['cookie', 'header'] })
54+
const req = {}
55+
const res = {
56+
headers: {
57+
'Set-Cookie': 'my=cookie'
58+
}
59+
}
60+
res.header = (name, value) => { res.headers[name] = value }
61+
ld.cacheUserLanguage(req, res, 'it', ['cookie'])
62+
expect(req).to.eql({})
63+
expect(res).to.have.property('headers')
64+
expect(res.headers).to.have.property('Set-Cookie')
65+
expect(res.headers['Set-Cookie']).to.match(/Path=\//)
66+
expect(res.headers['Set-Cookie']).to.match(/my=cookie/)
67+
expect(res.headers['Set-Cookie']).not.to.match(/HttpOnly/)
68+
})
69+
70+
it('does not set httpOnly flag when cookieHttpOnly is false', () => {
71+
const ld = new LanguageDetector(i18next.services, { order: ['cookie', 'header'], cookieHttpOnly: false })
72+
const req = {}
73+
const res = {
74+
headers: {
75+
'Set-Cookie': 'my=cookie'
76+
}
77+
}
78+
res.header = (name, value) => { res.headers[name] = value }
79+
ld.cacheUserLanguage(req, res, 'it', ['cookie'])
80+
expect(req).to.eql({})
81+
expect(res).to.have.property('headers')
82+
expect(res.headers).to.have.property('Set-Cookie')
83+
expect(res.headers['Set-Cookie']).to.match(/Path=\//)
84+
expect(res.headers['Set-Cookie']).to.match(/my=cookie/)
85+
expect(res.headers['Set-Cookie']).not.to.match(/HttpOnly/)
86+
})
87+
88+
it('sets httpOnly flag when cookieHttpOnly is true', () => {
89+
const ld = new LanguageDetector(i18next.services, { order: ['cookie', 'header'], cookieHttpOnly: true })
90+
const req = {}
91+
const res = {
92+
headers: {
93+
'Set-Cookie': 'my=cookie'
94+
}
95+
}
96+
res.header = (name, value) => { res.headers[name] = value }
97+
ld.cacheUserLanguage(req, res, 'it', ['cookie'])
98+
expect(req).to.eql({})
99+
expect(res).to.have.property('headers')
100+
expect(res.headers).to.have.property('Set-Cookie')
101+
expect(res.headers['Set-Cookie']).to.match(/Path=\//)
102+
expect(res.headers['Set-Cookie']).to.match(/my=cookie/)
103+
expect(res.headers['Set-Cookie']).to.match(/HttpOnly/)
104+
})
51105
})
52106

53107
describe('header', () => {

0 commit comments

Comments
 (0)