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.
		
		
		
		
		
			
		
			
				
					221 lines
				
				6.2 KiB
			
		
		
			
		
	
	
					221 lines
				
				6.2 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | 
 | ||
|  | var defaultParseOptions = { | ||
|  |   decodeValues: true, | ||
|  |   map: false, | ||
|  |   silent: false, | ||
|  | }; | ||
|  | 
 | ||
|  | function isNonEmptyString(str) { | ||
|  |   return typeof str === "string" && !!str.trim(); | ||
|  | } | ||
|  | 
 | ||
|  | function parseString(setCookieValue, options) { | ||
|  |   var parts = setCookieValue.split(";").filter(isNonEmptyString); | ||
|  | 
 | ||
|  |   var nameValuePairStr = parts.shift(); | ||
|  |   var parsed = parseNameValuePair(nameValuePairStr); | ||
|  |   var name = parsed.name; | ||
|  |   var value = parsed.value; | ||
|  | 
 | ||
|  |   options = options | ||
|  |     ? Object.assign({}, defaultParseOptions, options) | ||
|  |     : defaultParseOptions; | ||
|  | 
 | ||
|  |   try { | ||
|  |     value = options.decodeValues ? decodeURIComponent(value) : value; // decode cookie value
 | ||
|  |   } catch (e) { | ||
|  |     console.error( | ||
|  |       "set-cookie-parser encountered an error while decoding a cookie with value '" + | ||
|  |         value + | ||
|  |         "'. Set options.decodeValues to false to disable this feature.", | ||
|  |       e | ||
|  |     ); | ||
|  |   } | ||
|  | 
 | ||
|  |   var cookie = { | ||
|  |     name: name, | ||
|  |     value: value, | ||
|  |   }; | ||
|  | 
 | ||
|  |   parts.forEach(function (part) { | ||
|  |     var sides = part.split("="); | ||
|  |     var key = sides.shift().trimLeft().toLowerCase(); | ||
|  |     var value = sides.join("="); | ||
|  |     if (key === "expires") { | ||
|  |       cookie.expires = new Date(value); | ||
|  |     } else if (key === "max-age") { | ||
|  |       cookie.maxAge = parseInt(value, 10); | ||
|  |     } else if (key === "secure") { | ||
|  |       cookie.secure = true; | ||
|  |     } else if (key === "httponly") { | ||
|  |       cookie.httpOnly = true; | ||
|  |     } else if (key === "samesite") { | ||
|  |       cookie.sameSite = value; | ||
|  |     } else { | ||
|  |       cookie[key] = value; | ||
|  |     } | ||
|  |   }); | ||
|  | 
 | ||
|  |   return cookie; | ||
|  | } | ||
|  | 
 | ||
|  | function parseNameValuePair(nameValuePairStr) { | ||
|  |   // Parses name-value-pair according to rfc6265bis draft
 | ||
|  | 
 | ||
|  |   var name = ""; | ||
|  |   var value = ""; | ||
|  |   var nameValueArr = nameValuePairStr.split("="); | ||
|  |   if (nameValueArr.length > 1) { | ||
|  |     name = nameValueArr.shift(); | ||
|  |     value = nameValueArr.join("="); // everything after the first =, joined by a "=" if there was more than one part
 | ||
|  |   } else { | ||
|  |     value = nameValuePairStr; | ||
|  |   } | ||
|  | 
 | ||
|  |   return { name: name, value: value }; | ||
|  | } | ||
|  | 
 | ||
|  | function parse(input, options) { | ||
|  |   options = options | ||
|  |     ? Object.assign({}, defaultParseOptions, options) | ||
|  |     : defaultParseOptions; | ||
|  | 
 | ||
|  |   if (!input) { | ||
|  |     if (!options.map) { | ||
|  |       return []; | ||
|  |     } else { | ||
|  |       return {}; | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   if (input.headers && input.headers["set-cookie"]) { | ||
|  |     // fast-path for node.js (which automatically normalizes header names to lower-case
 | ||
|  |     input = input.headers["set-cookie"]; | ||
|  |   } else if (input.headers) { | ||
|  |     // slow-path for other environments - see #25
 | ||
|  |     var sch = | ||
|  |       input.headers[ | ||
|  |         Object.keys(input.headers).find(function (key) { | ||
|  |           return key.toLowerCase() === "set-cookie"; | ||
|  |         }) | ||
|  |       ]; | ||
|  |     // warn if called on a request-like object with a cookie header rather than a set-cookie header - see #34, 36
 | ||
|  |     if (!sch && input.headers.cookie && !options.silent) { | ||
|  |       console.warn( | ||
|  |         "Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning." | ||
|  |       ); | ||
|  |     } | ||
|  |     input = sch; | ||
|  |   } | ||
|  |   if (!Array.isArray(input)) { | ||
|  |     input = [input]; | ||
|  |   } | ||
|  | 
 | ||
|  |   options = options | ||
|  |     ? Object.assign({}, defaultParseOptions, options) | ||
|  |     : defaultParseOptions; | ||
|  | 
 | ||
|  |   if (!options.map) { | ||
|  |     return input.filter(isNonEmptyString).map(function (str) { | ||
|  |       return parseString(str, options); | ||
|  |     }); | ||
|  |   } else { | ||
|  |     var cookies = {}; | ||
|  |     return input.filter(isNonEmptyString).reduce(function (cookies, str) { | ||
|  |       var cookie = parseString(str, options); | ||
|  |       cookies[cookie.name] = cookie; | ||
|  |       return cookies; | ||
|  |     }, cookies); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | /* | ||
|  |   Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas | ||
|  |   that are within a single set-cookie field-value, such as in the Expires portion. | ||
|  | 
 | ||
|  |   This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2
 | ||
|  |   Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128
 | ||
|  |   React Native's fetch does this for *every* header, including set-cookie. | ||
|  | 
 | ||
|  |   Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25
 | ||
|  |   Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation
 | ||
|  | */ | ||
|  | function splitCookiesString(cookiesString) { | ||
|  |   if (Array.isArray(cookiesString)) { | ||
|  |     return cookiesString; | ||
|  |   } | ||
|  |   if (typeof cookiesString !== "string") { | ||
|  |     return []; | ||
|  |   } | ||
|  | 
 | ||
|  |   var cookiesStrings = []; | ||
|  |   var pos = 0; | ||
|  |   var start; | ||
|  |   var ch; | ||
|  |   var lastComma; | ||
|  |   var nextStart; | ||
|  |   var cookiesSeparatorFound; | ||
|  | 
 | ||
|  |   function skipWhitespace() { | ||
|  |     while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) { | ||
|  |       pos += 1; | ||
|  |     } | ||
|  |     return pos < cookiesString.length; | ||
|  |   } | ||
|  | 
 | ||
|  |   function notSpecialChar() { | ||
|  |     ch = cookiesString.charAt(pos); | ||
|  | 
 | ||
|  |     return ch !== "=" && ch !== ";" && ch !== ","; | ||
|  |   } | ||
|  | 
 | ||
|  |   while (pos < cookiesString.length) { | ||
|  |     start = pos; | ||
|  |     cookiesSeparatorFound = false; | ||
|  | 
 | ||
|  |     while (skipWhitespace()) { | ||
|  |       ch = cookiesString.charAt(pos); | ||
|  |       if (ch === ",") { | ||
|  |         // ',' is a cookie separator if we have later first '=', not ';' or ','
 | ||
|  |         lastComma = pos; | ||
|  |         pos += 1; | ||
|  | 
 | ||
|  |         skipWhitespace(); | ||
|  |         nextStart = pos; | ||
|  | 
 | ||
|  |         while (pos < cookiesString.length && notSpecialChar()) { | ||
|  |           pos += 1; | ||
|  |         } | ||
|  | 
 | ||
|  |         // currently special character
 | ||
|  |         if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") { | ||
|  |           // we found cookies separator
 | ||
|  |           cookiesSeparatorFound = true; | ||
|  |           // pos is inside the next cookie, so back up and return it.
 | ||
|  |           pos = nextStart; | ||
|  |           cookiesStrings.push(cookiesString.substring(start, lastComma)); | ||
|  |           start = pos; | ||
|  |         } else { | ||
|  |           // in param ',' or param separator ';',
 | ||
|  |           // we continue from that comma
 | ||
|  |           pos = lastComma + 1; | ||
|  |         } | ||
|  |       } else { | ||
|  |         pos += 1; | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     if (!cookiesSeparatorFound || pos >= cookiesString.length) { | ||
|  |       cookiesStrings.push(cookiesString.substring(start, cookiesString.length)); | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   return cookiesStrings; | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = parse; | ||
|  | module.exports.parse = parse; | ||
|  | module.exports.parseString = parseString; | ||
|  | module.exports.splitCookiesString = splitCookiesString; |