root / HServer / 00.Server / 00.Program / node_modules / cookie / index.js
이력 | 보기 | 이력해설 | 다운로드 (3.88 KB)
1 | 39 | HKM | /*!
|
---|---|---|---|
2 | * cookie
|
||
3 | * Copyright(c) 2012-2014 Roman Shtylman
|
||
4 | * Copyright(c) 2015 Douglas Christopher Wilson
|
||
5 | * MIT Licensed
|
||
6 | */
|
||
7 | |||
8 | 'use strict';
|
||
9 | |||
10 | /**
|
||
11 | * Module exports.
|
||
12 | * @public
|
||
13 | */
|
||
14 | |||
15 | exports.parse = parse; |
||
16 | exports.serialize = serialize; |
||
17 | |||
18 | /**
|
||
19 | * Module variables.
|
||
20 | * @private
|
||
21 | */
|
||
22 | |||
23 | var decode = decodeURIComponent;
|
||
24 | var encode = encodeURIComponent;
|
||
25 | var pairSplitRegExp = /; */; |
||
26 | |||
27 | /**
|
||
28 | * RegExp to match field-content in RFC 7230 sec 3.2
|
||
29 | *
|
||
30 | * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
|
||
31 | * field-vchar = VCHAR / obs-text
|
||
32 | * obs-text = %x80-FF
|
||
33 | */
|
||
34 | |||
35 | var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; |
||
36 | |||
37 | /**
|
||
38 | * Parse a cookie header.
|
||
39 | *
|
||
40 | * Parse the given cookie header string into an object
|
||
41 | * The object has the various cookies as keys(names) => values
|
||
42 | *
|
||
43 | * @param {string} str
|
||
44 | * @param {object} [options]
|
||
45 | * @return {object}
|
||
46 | * @public
|
||
47 | */
|
||
48 | |||
49 | function parse(str, options) { |
||
50 | if (typeof str !== 'string') { |
||
51 | throw new TypeError('argument str must be a string'); |
||
52 | } |
||
53 | |||
54 | var obj = {}
|
||
55 | var opt = options || {};
|
||
56 | var pairs = str.split(pairSplitRegExp);
|
||
57 | var dec = opt.decode || decode;
|
||
58 | |||
59 | for (var i = 0; i < pairs.length; i++) { |
||
60 | var pair = pairs[i];
|
||
61 | var eq_idx = pair.indexOf('='); |
||
62 | |||
63 | // skip things that don't look like key=value
|
||
64 | if (eq_idx < 0) { |
||
65 | continue;
|
||
66 | } |
||
67 | |||
68 | var key = pair.substr(0, eq_idx).trim() |
||
69 | var val = pair.substr(++eq_idx, pair.length).trim();
|
||
70 | |||
71 | // quoted values
|
||
72 | if ('"' == val[0]) { |
||
73 | val = val.slice(1, -1); |
||
74 | } |
||
75 | |||
76 | // only assign once
|
||
77 | if (undefined == obj[key]) { |
||
78 | obj[key] = tryDecode(val, dec); |
||
79 | } |
||
80 | } |
||
81 | |||
82 | return obj;
|
||
83 | } |
||
84 | |||
85 | /**
|
||
86 | * Serialize data into a cookie header.
|
||
87 | *
|
||
88 | * Serialize the a name value pair into a cookie string suitable for
|
||
89 | * http headers. An optional options object specified cookie parameters.
|
||
90 | *
|
||
91 | * serialize('foo', 'bar', { httpOnly: true })
|
||
92 | * => "foo=bar; httpOnly"
|
||
93 | *
|
||
94 | * @param {string} name
|
||
95 | * @param {string} val
|
||
96 | * @param {object} [options]
|
||
97 | * @return {string}
|
||
98 | * @public
|
||
99 | */
|
||
100 | |||
101 | function serialize(name, val, options) { |
||
102 | var opt = options || {};
|
||
103 | var enc = opt.encode || encode;
|
||
104 | |||
105 | if (typeof enc !== 'function') { |
||
106 | throw new TypeError('option encode is invalid'); |
||
107 | } |
||
108 | |||
109 | if (!fieldContentRegExp.test(name)) {
|
||
110 | throw new TypeError('argument name is invalid'); |
||
111 | } |
||
112 | |||
113 | var value = enc(val);
|
||
114 | |||
115 | if (value && !fieldContentRegExp.test(value)) {
|
||
116 | throw new TypeError('argument val is invalid'); |
||
117 | } |
||
118 | |||
119 | var str = name + '=' + value; |
||
120 | |||
121 | if (null != opt.maxAge) { |
||
122 | var maxAge = opt.maxAge - 0; |
||
123 | if (isNaN(maxAge)) throw new Error('maxAge should be a Number'); |
||
124 | str += '; Max-Age=' + Math.floor(maxAge);
|
||
125 | } |
||
126 | |||
127 | if (opt.domain) {
|
||
128 | if (!fieldContentRegExp.test(opt.domain)) {
|
||
129 | throw new TypeError('option domain is invalid'); |
||
130 | } |
||
131 | |||
132 | str += '; Domain=' + opt.domain;
|
||
133 | } |
||
134 | |||
135 | if (opt.path) {
|
||
136 | if (!fieldContentRegExp.test(opt.path)) {
|
||
137 | throw new TypeError('option path is invalid'); |
||
138 | } |
||
139 | |||
140 | str += '; Path=' + opt.path;
|
||
141 | } |
||
142 | |||
143 | if (opt.expires) {
|
||
144 | if (typeof opt.expires.toUTCString !== 'function') { |
||
145 | throw new TypeError('option expires is invalid'); |
||
146 | } |
||
147 | |||
148 | str += '; Expires=' + opt.expires.toUTCString();
|
||
149 | } |
||
150 | |||
151 | if (opt.httpOnly) {
|
||
152 | str += '; HttpOnly';
|
||
153 | } |
||
154 | |||
155 | if (opt.secure) {
|
||
156 | str += '; Secure';
|
||
157 | } |
||
158 | |||
159 | if (opt.sameSite) {
|
||
160 | var sameSite = typeof opt.sameSite === 'string' |
||
161 | ? opt.sameSite.toLowerCase() : opt.sameSite; |
||
162 | |||
163 | switch (sameSite) {
|
||
164 | case true: |
||
165 | str += '; SameSite=Strict';
|
||
166 | break;
|
||
167 | case 'lax': |
||
168 | str += '; SameSite=Lax';
|
||
169 | break;
|
||
170 | case 'strict': |
||
171 | str += '; SameSite=Strict';
|
||
172 | break;
|
||
173 | default:
|
||
174 | throw new TypeError('option sameSite is invalid'); |
||
175 | } |
||
176 | } |
||
177 | |||
178 | return str;
|
||
179 | } |
||
180 | |||
181 | /**
|
||
182 | * Try decoding a string using a decoding function.
|
||
183 | *
|
||
184 | * @param {string} str
|
||
185 | * @param {function} decode
|
||
186 | * @private
|
||
187 | */
|
||
188 | |||
189 | function tryDecode(str, decode) { |
||
190 | try {
|
||
191 | return decode(str);
|
||
192 | } catch (e) {
|
||
193 | return str;
|
||
194 | } |
||
195 | } |