-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathcookie.ts
More file actions
111 lines (96 loc) · 3.56 KB
/
Copy pathcookie.ts
File metadata and controls
111 lines (96 loc) · 3.56 KB
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
import { ONE_SECOND } from '../tools/utils/timeUtils'
import {
findAllCommaSeparatedValues,
findCommaSeparatedValue,
findCommaSeparatedValues,
generateUUID,
} from '../tools/utils/stringUtils'
import { buildUrl } from '../tools/utils/urlPolyfill'
export interface CookieOptions {
secure?: boolean
crossSite?: boolean
partitioned?: boolean
domain?: string
}
export function setCookie(name: string, value: string, expireDelay: number = 0, options?: CookieOptions) {
const date = new Date()
date.setTime(date.getTime() + expireDelay)
const expires = `expires=${date.toUTCString()}`
const sameSite = options && options.crossSite ? 'none' : 'strict'
const domain = options && options.domain ? `;domain=${options.domain}` : ''
const secure = options && options.secure ? ';secure' : ''
const partitioned = options && options.partitioned ? ';partitioned' : ''
document.cookie = `${name}=${value};${expires};path=/;samesite=${sameSite}${domain}${secure}${partitioned}`
}
/**
* Returns the value of the cookie with the given name
* If there are multiple cookies with the same name, returns the first one
*/
export function getCookie(name: string) {
const value = findCommaSeparatedValue(document.cookie, name)
if (value === '') {
return
}
return value
}
/**
* Returns all the values of the cookies with the given name
*/
export function getCookies(name: string): string[] {
return findAllCommaSeparatedValues(document.cookie).get(name) || []
}
let initCookieParsed: Map<string, string> | undefined
/**
* Returns a cached value of the cookie. Use this during SDK initialization (and whenever possible)
* to avoid accessing document.cookie multiple times.
*
* ⚠️ If there are multiple cookies with the same name, returns the LAST one (unlike `getCookie()`)
*/
export function getInitCookie(name: string) {
if (!initCookieParsed) {
initCookieParsed = findCommaSeparatedValues(document.cookie)
}
return initCookieParsed.get(name)
}
export function resetInitCookies() {
initCookieParsed = undefined
}
export function deleteCookie(name: string, options?: CookieOptions) {
setCookie(name, '', 0, options)
}
/**
* No API to retrieve it, number of levels for subdomain and suffix are unknown
* strategy: find the minimal domain on which cookies are allowed to be set
* https://web.dev/same-site-same-origin/#site
*/
let getCurrentSiteCache: string | undefined
export function getCurrentSite(hostname = location.hostname, referrer = document.referrer): string | undefined {
if (getCurrentSiteCache === undefined) {
const defaultHostName = getCookieDefaultHostName(hostname, referrer)
if (defaultHostName) {
// Use a unique cookie name to avoid issues when the SDK is initialized multiple times during
// the test cookie lifetime
const testCookieName = `dd_site_test_${generateUUID()}`
const testCookieValue = 'test'
const domainLevels = defaultHostName.split('.')
let candidateDomain = domainLevels.pop()!
while (domainLevels.length && !getCookie(testCookieName)) {
candidateDomain = `${domainLevels.pop()!}.${candidateDomain}`
setCookie(testCookieName, testCookieValue, ONE_SECOND, { domain: candidateDomain })
}
deleteCookie(testCookieName, { domain: candidateDomain })
getCurrentSiteCache = candidateDomain
}
}
return getCurrentSiteCache
}
function getCookieDefaultHostName(hostname: string, referrer: string) {
try {
return hostname || buildUrl(referrer).hostname
} catch {
// Ignore
}
}
export function resetGetCurrentSite() {
getCurrentSiteCache = undefined
}