-
-
Notifications
You must be signed in to change notification settings - Fork 207
/
CookieStringUtility.ts
116 lines (103 loc) · 2.59 KB
/
CookieStringUtility.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import CookieSameSiteEnum from '../enums/CookieSameSiteEnum.js';
import URL from '../../url/URL.js';
import ICookie from '../ICookie.js';
/**
* Cookie string.
*/
export default class CookieStringUtility {
/**
* Returns cookie.
*
* @param originURL Origin URL.
* @param cookieString Cookie string.
* @returns Cookie.
*/
public static stringToCookie(originURL: URL, cookieString: string): ICookie | null {
const parts = cookieString.split(';');
const [key, value] = parts.shift().split('=');
const cookie: ICookie = {
// Required
key: key.trim(),
value: value ?? null,
originURL,
// Optional
domain: '',
path: '',
expires: null,
httpOnly: false,
secure: false,
sameSite: CookieSameSiteEnum.lax
};
// Invalid if key is empty.
if (!cookie.key) {
return null;
}
for (const part of parts) {
const keyAndValue = part.split('=');
const key = keyAndValue[0].trim().toLowerCase();
const value = keyAndValue[1];
switch (key) {
case 'expires':
cookie.expires = new Date(value);
break;
case 'max-age':
cookie.expires = new Date(parseInt(value, 10) * 1000 + Date.now());
break;
case 'domain':
cookie.domain = value;
break;
case 'path':
cookie.path = value.startsWith('/') ? value : `/${value}`;
break;
case 'httponly':
cookie.httpOnly = true;
break;
case 'secure':
cookie.secure = true;
break;
case 'samesite':
switch (value.toLowerCase()) {
case 'strict':
cookie.sameSite = CookieSameSiteEnum.strict;
break;
case 'lax':
cookie.sameSite = CookieSameSiteEnum.lax;
break;
case 'none':
cookie.sameSite = CookieSameSiteEnum.none;
}
break;
}
}
const lowerKey = cookie.key.toLowerCase();
// Invalid if __secure- prefix is used and cookie is not secure.
if (lowerKey.startsWith('__secure-') && !cookie.secure) {
return null;
}
// Invalid if __host- prefix is used and cookie is not secure, not on root path or has a domain.
if (
lowerKey.startsWith('__host-') &&
(!cookie.secure || cookie.path !== '/' || cookie.domain)
) {
return null;
}
return cookie;
}
/**
* Returns cookie string with key and value.
*
* @param cookies Cookies.
* @returns Cookie string.
*/
public static cookiesToString(cookies: ICookie[]): string {
const cookieString: string[] = [];
for (const cookie of cookies) {
if (cookie.value !== null) {
cookieString.push(`${cookie.key}=${cookie.value}`);
} else {
cookieString.push(cookie.key);
}
}
return cookieString.join('; ');
}
}