aboutsummaryrefslogtreecommitdiff
path: root/node_modules/cookies/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/cookies/index.js')
-rw-r--r--node_modules/cookies/index.js220
1 files changed, 220 insertions, 0 deletions
diff --git a/node_modules/cookies/index.js b/node_modules/cookies/index.js
new file mode 100644
index 00000000..9c468ae9
--- /dev/null
+++ b/node_modules/cookies/index.js
@@ -0,0 +1,220 @@
+/*!
+ * cookies
+ * Copyright(c) 2014 Jed Schmidt, http://jed.is/
+ * Copyright(c) 2015-2016 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+var deprecate = require('depd')('cookies')
+var Keygrip = require('keygrip')
+var http = require('http')
+var cache = {}
+
+/**
+ * RegExp to match field-content in RFC 7230 sec 3.2
+ *
+ * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+ * field-vchar = VCHAR / obs-text
+ * obs-text = %x80-FF
+ */
+
+var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
+
+/**
+ * RegExp to match Same-Site cookie attribute value.
+ */
+
+var sameSiteRegExp = /^(?:lax|strict)$/i
+
+function Cookies(request, response, options) {
+ if (!(this instanceof Cookies)) return new Cookies(request, response, options)
+
+ this.secure = undefined
+ this.request = request
+ this.response = response
+
+ if (options) {
+ if (Array.isArray(options)) {
+ // array of key strings
+ deprecate('"keys" argument; provide using options {"keys": [...]}')
+ this.keys = new Keygrip(options)
+ } else if (options.constructor && options.constructor.name === 'Keygrip') {
+ // any keygrip constructor to allow different versions
+ deprecate('"keys" argument; provide using options {"keys": keygrip}')
+ this.keys = options
+ } else {
+ this.keys = Array.isArray(options.keys) ? new Keygrip(options.keys) : options.keys
+ this.secure = options.secure
+ }
+ }
+}
+
+Cookies.prototype.get = function(name, opts) {
+ var sigName = name + ".sig"
+ , header, match, value, remote, data, index
+ , signed = opts && opts.signed !== undefined ? opts.signed : !!this.keys
+
+ header = this.request.headers["cookie"]
+ if (!header) return
+
+ match = header.match(getPattern(name))
+ if (!match) return
+
+ value = match[1]
+ if (!opts || !signed) return value
+
+ remote = this.get(sigName)
+ if (!remote) return
+
+ data = name + "=" + value
+ if (!this.keys) throw new Error('.keys required for signed cookies');
+ index = this.keys.index(data, remote)
+
+ if (index < 0) {
+ this.set(sigName, null, {path: "/", signed: false })
+ } else {
+ index && this.set(sigName, this.keys.sign(data), { signed: false })
+ return value
+ }
+};
+
+Cookies.prototype.set = function(name, value, opts) {
+ var res = this.response
+ , req = this.request
+ , headers = res.getHeader("Set-Cookie") || []
+ , secure = this.secure !== undefined ? !!this.secure : req.protocol === 'https' || req.connection.encrypted
+ , cookie = new Cookie(name, value, opts)
+ , signed = opts && opts.signed !== undefined ? opts.signed : !!this.keys
+
+ if (typeof headers == "string") headers = [headers]
+
+ if (!secure && opts && opts.secure) {
+ throw new Error('Cannot send secure cookie over unencrypted connection')
+ }
+
+ cookie.secure = secure
+ if (opts && "secure" in opts) cookie.secure = opts.secure
+
+ if (opts && "secureProxy" in opts) {
+ deprecate('"secureProxy" option; use "secure" option, provide "secure" to constructor if needed')
+ cookie.secure = opts.secureProxy
+ }
+
+ pushCookie(headers, cookie)
+
+ if (opts && signed) {
+ if (!this.keys) throw new Error('.keys required for signed cookies');
+ cookie.value = this.keys.sign(cookie.toString())
+ cookie.name += ".sig"
+ pushCookie(headers, cookie)
+ }
+
+ var setHeader = res.set ? http.OutgoingMessage.prototype.setHeader : res.setHeader
+ setHeader.call(res, 'Set-Cookie', headers)
+ return this
+};
+
+function Cookie(name, value, attrs) {
+ if (!fieldContentRegExp.test(name)) {
+ throw new TypeError('argument name is invalid');
+ }
+
+ if (value && !fieldContentRegExp.test(value)) {
+ throw new TypeError('argument value is invalid');
+ }
+
+ value || (this.expires = new Date(0))
+
+ this.name = name
+ this.value = value || ""
+
+ for (var name in attrs) {
+ this[name] = attrs[name]
+ }
+
+ if (this.path && !fieldContentRegExp.test(this.path)) {
+ throw new TypeError('option path is invalid');
+ }
+
+ if (this.domain && !fieldContentRegExp.test(this.domain)) {
+ throw new TypeError('option domain is invalid');
+ }
+
+ if (this.sameSite && this.sameSite !== true && !sameSiteRegExp.test(this.sameSite)) {
+ throw new TypeError('option sameSite is invalid')
+ }
+}
+
+Cookie.prototype.path = "/";
+Cookie.prototype.expires = undefined;
+Cookie.prototype.domain = undefined;
+Cookie.prototype.httpOnly = true;
+Cookie.prototype.sameSite = false;
+Cookie.prototype.secure = false;
+Cookie.prototype.overwrite = false;
+
+Cookie.prototype.toString = function() {
+ return this.name + "=" + this.value
+};
+
+Cookie.prototype.toHeader = function() {
+ var header = this.toString()
+
+ if (this.maxAge) this.expires = new Date(Date.now() + this.maxAge);
+
+ if (this.path ) header += "; path=" + this.path
+ if (this.expires ) header += "; expires=" + this.expires.toUTCString()
+ if (this.domain ) header += "; domain=" + this.domain
+ if (this.sameSite ) header += "; samesite=" + (this.sameSite === true ? 'strict' : this.sameSite.toLowerCase())
+ if (this.secure ) header += "; secure"
+ if (this.httpOnly ) header += "; httponly"
+
+ return header
+};
+
+// back-compat so maxage mirrors maxAge
+Object.defineProperty(Cookie.prototype, 'maxage', {
+ configurable: true,
+ enumerable: true,
+ get: function () { return this.maxAge },
+ set: function (val) { return this.maxAge = val }
+});
+deprecate.property(Cookie.prototype, 'maxage', '"maxage"; use "maxAge" instead')
+
+function getPattern(name) {
+ if (cache[name]) return cache[name]
+
+ return cache[name] = new RegExp(
+ "(?:^|;) *" +
+ name.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") +
+ "=([^;]*)"
+ )
+}
+
+function pushCookie(headers, cookie) {
+ if (cookie.overwrite) {
+ for (var i = headers.length - 1; i >= 0; i--) {
+ if (headers[i].indexOf(cookie.name + '=') === 0) {
+ headers.splice(i, 1)
+ }
+ }
+ }
+
+ headers.push(cookie.toHeader())
+}
+
+Cookies.connect = Cookies.express = function(keys) {
+ return function(req, res, next) {
+ req.cookies = res.cookies = new Cookies(req, res, {
+ keys: keys
+ })
+
+ next()
+ }
+}
+
+Cookies.Cookie = Cookie
+
+module.exports = Cookies