You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
3.3 KiB
182 lines
3.3 KiB
/*! |
|
* cookie-parser |
|
* Copyright(c) 2014 TJ Holowaychuk |
|
* Copyright(c) 2015 Douglas Christopher Wilson |
|
* MIT Licensed |
|
*/ |
|
|
|
'use strict' |
|
|
|
/** |
|
* Module dependencies. |
|
* @private |
|
*/ |
|
|
|
var cookie = require('cookie') |
|
var signature = require('cookie-signature') |
|
|
|
/** |
|
* Module exports. |
|
* @public |
|
*/ |
|
|
|
module.exports = cookieParser |
|
module.exports.JSONCookie = JSONCookie |
|
module.exports.JSONCookies = JSONCookies |
|
module.exports.signedCookie = signedCookie |
|
module.exports.signedCookies = signedCookies |
|
|
|
/** |
|
* Parse Cookie header and populate `req.cookies` |
|
* with an object keyed by the cookie names. |
|
* |
|
* @param {string|array} [secret] A string (or array of strings) representing cookie signing secret(s). |
|
* @param {Object} [options] |
|
* @return {Function} |
|
* @public |
|
*/ |
|
|
|
function cookieParser (secret, options) { |
|
var secrets = !secret || Array.isArray(secret) |
|
? (secret || []) |
|
: [secret] |
|
|
|
return function cookieParser (req, res, next) { |
|
if (req.cookies) { |
|
return next() |
|
} |
|
|
|
var cookies = req.headers.cookie |
|
|
|
req.secret = secrets[0] |
|
req.cookies = Object.create(null) |
|
req.signedCookies = Object.create(null) |
|
|
|
// no cookies |
|
if (!cookies) { |
|
return next() |
|
} |
|
|
|
req.cookies = cookie.parse(cookies, options) |
|
|
|
// parse signed cookies |
|
if (secrets.length !== 0) { |
|
req.signedCookies = signedCookies(req.cookies, secrets) |
|
req.signedCookies = JSONCookies(req.signedCookies) |
|
} |
|
|
|
// parse JSON cookies |
|
req.cookies = JSONCookies(req.cookies) |
|
|
|
next() |
|
} |
|
} |
|
|
|
/** |
|
* Parse JSON cookie string. |
|
* |
|
* @param {String} str |
|
* @return {Object} Parsed object or undefined if not json cookie |
|
* @public |
|
*/ |
|
|
|
function JSONCookie (str) { |
|
if (typeof str !== 'string' || str.substr(0, 2) !== 'j:') { |
|
return undefined |
|
} |
|
|
|
try { |
|
return JSON.parse(str.slice(2)) |
|
} catch (err) { |
|
return undefined |
|
} |
|
} |
|
|
|
/** |
|
* Parse JSON cookies. |
|
* |
|
* @param {Object} obj |
|
* @return {Object} |
|
* @public |
|
*/ |
|
|
|
function JSONCookies (obj) { |
|
var cookies = Object.keys(obj) |
|
var key |
|
var val |
|
|
|
for (var i = 0; i < cookies.length; i++) { |
|
key = cookies[i] |
|
val = JSONCookie(obj[key]) |
|
|
|
if (val) { |
|
obj[key] = val |
|
} |
|
} |
|
|
|
return obj |
|
} |
|
|
|
/** |
|
* Parse a signed cookie string, return the decoded value. |
|
* |
|
* @param {String} str signed cookie string |
|
* @param {string|array} secret |
|
* @return {String} decoded value |
|
* @public |
|
*/ |
|
|
|
function signedCookie (str, secret) { |
|
if (typeof str !== 'string') { |
|
return undefined |
|
} |
|
|
|
if (str.substr(0, 2) !== 's:') { |
|
return str |
|
} |
|
|
|
var secrets = !secret || Array.isArray(secret) |
|
? (secret || []) |
|
: [secret] |
|
|
|
for (var i = 0; i < secrets.length; i++) { |
|
var val = signature.unsign(str.slice(2), secrets[i]) |
|
|
|
if (val !== false) { |
|
return val |
|
} |
|
} |
|
|
|
return false |
|
} |
|
|
|
/** |
|
* Parse signed cookies, returning an object containing the decoded key/value |
|
* pairs, while removing the signed key from obj. |
|
* |
|
* @param {Object} obj |
|
* @param {string|array} secret |
|
* @return {Object} |
|
* @public |
|
*/ |
|
|
|
function signedCookies (obj, secret) { |
|
var cookies = Object.keys(obj) |
|
var dec |
|
var key |
|
var ret = Object.create(null) |
|
var val |
|
|
|
for (var i = 0; i < cookies.length; i++) { |
|
key = cookies[i] |
|
val = obj[key] |
|
dec = signedCookie(val, secret) |
|
|
|
if (val !== dec) { |
|
ret[key] = dec |
|
delete obj[key] |
|
} |
|
} |
|
|
|
return ret |
|
}
|
|
|